Browse Source

Sol Part 64: Now with Less Non-Deterministic "Electric" Strangs!

Pursuant some fuzzing, *most* places where a SOL_STRING (C string)
escaped to the user are now replaced with SOL_BUFFER. This allows,
amongst other things, source strings to contain embedded NUL characters.

Also, a fix for comma-after-empty-list in the parser is implemented.
Graham Northup 3 years ago
parent
commit
705065925b
Signed by: Graham Northup <grissess@nexusg.org> GPG Key ID: 5D000E6F539376FB
18 changed files with 808 additions and 313 deletions
  1. 1
    0
      .gitignore
  2. 1
    1
      Makefile
  3. 3
    0
      RECIPES
  4. 10
    1
      ast.h
  5. 4
    0
      astprint.c
  6. 366
    33
      builtins.c
  7. 141
    196
      lex.yy.c
  8. 60
    2
      object.c
  9. 58
    44
      parser.tab.c
  10. 40
    19
      parser.y
  11. 3
    3
      programs/test.sol
  12. 15
    0
      runtime.c
  13. 29
    0
      ser.c
  14. 37
    3
      sol.h
  15. 29
    8
      state.c
  16. BIN
      tests/crasher_embedded_nul.sol
  17. 9
    0
      tests/crasher_init_comma.sol
  18. 2
    3
      tokenizer.lex

+ 1
- 0
.gitignore View File

@@ -15,3 +15,4 @@ doxyxml
15 15
 valgrind.log
16 16
 *_INFO
17 17
 prof
18
+/afl

+ 1
- 1
Makefile View File

@@ -67,7 +67,7 @@ $(LINKED_VERS): sol$(SOL_VER)
67 67
 	rm $@; ln -s $? $@
68 68
 	
69 69
 sol$(SOL_VER): $(OBJ)
70
-	$(CC) $(CFLAGS) $? $(LDFLAGS) -o $@
70
+	$(CC) $(CFLAGS) $^ $(LDFLAGS) -o $@
71 71
 
72 72
 test: all $(sort $(patsubst tests/%.sol,test_%,$(wildcard tests/*.sol))) $(sort $(patsubst tests/%.sol,testcomp_%,$(wildcard tests/*.sol)))
73 73
 

+ 3
- 0
RECIPES View File

@@ -6,3 +6,6 @@ make CC=clang CFLAGS="-fprofile-instr-generate -fcoverage-mapping"
6 6
 
7 7
 use Boehm GC where available:
8 8
 make LDFLAGS=-lgc
9
+
10
+AFL fuzzing (use afl-fuzz on the resulting instrumented binary):
11
+make CC=afl-gcc

+ 10
- 1
ast.h View File

@@ -24,7 +24,7 @@ typedef struct tag_stmt_node stmt_node;
24 24
  *
25 25
  * Defines the types of literals that may appear in a source program.
26 26
  */
27
-typedef enum {LIT_INT=1024, LIT_FLOAT, LIT_STRING, LIT_NONE} lit_t;
27
+typedef enum {LIT_INT=1024, LIT_FLOAT, LIT_STRING, LIT_BUFFER, LIT_NONE} lit_t;
28 28
 /** Literal node
29 29
  *
30 30
  * Represents a literal in a source program.
@@ -35,9 +35,15 @@ typedef struct {
35 35
 		long ival; ///< Integer value for `LIT_INT`.
36 36
 		double fval; ///< Floating-point value for `LIT_FLOAT`.
37 37
 		char *str; ///< String value for `LIT_STRING`.
38
+		unsigned long *buf; ///< Buffer value for `LIT_BUFFER`; points to. (char *)(buf + 1) points to the first byte in the buffer. There are *buf bytes starting there. See also LENGTH_OF and BYTES_OF.
38 39
 	};
39 40
 } lit_node;
40 41
 
42
+/** Returns the length (as an unsigned long) of the buffer in bytes, not including the length itself. */
43
+#define LENGTH_OF(buf) (*((unsigned long *) (buf)))
44
+/** Returns a (char *) pointing to the first byte in the buffer. */
45
+#define BYTES_OF(buf) ((char *) (((unsigned long *) (buf)) + 1))
46
+
41 47
 /** Binary operation type
42 48
  *
43 49
  * Defines the types of binary operators that may occur in a source program.
@@ -237,10 +243,12 @@ typedef enum {
237 243
 	BC_LIT_INT,
238 244
 	BC_LIT_FLOAT,
239 245
 	BC_LIT_STRING,
246
+	BC_LIT_BUFFER,
240 247
 	BC_LIT_NONE,
241 248
 	BC_INT,
242 249
 	BC_FLOAT,
243 250
 	BC_STRING,
251
+	BC_BUFFER,
244 252
 	BC_LIST_ST,
245 253
 	BC_LIST_EX,
246 254
 	BC_LIST_AS,
@@ -333,6 +341,7 @@ void sol_ser_lit(FILE *, lit_node *);
333 341
 void sol_ser_int(FILE *, long);
334 342
 void sol_ser_float(FILE *, double);
335 343
 void sol_ser_str(FILE *, const char *);
344
+void sol_ser_buf(FILE *, unsigned long *);
336 345
 
337 346
 void *sol_deser(FILE *);
338 347
 void *sol_deser_checked(FILE *, bytecode);

+ 4
- 0
astprint.c View File

@@ -82,6 +82,10 @@ void prex(sol_state_t *state, expr_node *node, int lev) {
82 82
 					prlev(state, lev, "String: %s", node->lit->str);
83 83
 					break;
84 84
 
85
+				case LIT_BUFFER:
86
+					prlev(state, lev, "Buffer of %lu bytes:", LENGTH_OF(node->lit->buf));
87
+					prlev(state, lev + 1, "%s", BYTES_OF(node->lit->buf));
88
+
85 89
 				case LIT_NONE:
86 90
 					prlev(state, lev, "None");
87 91
 					break;

+ 366
- 33
builtins.c View File

@@ -1,3 +1,4 @@
1
+#define _GNU_SOURCE
1 2
 #include <string.h>
2 3
 #include <stdlib.h>
3 4
 #include <stdio.h>
@@ -59,6 +60,14 @@ sol_object_t *sol_f_default_repr(sol_state_t *state, sol_object_t *args) {
59 60
 	return res;
60 61
 }
61 62
 
63
+sol_object_t *sol_f_default_tobuffer(sol_state_t *state, sol_object_t *args) {
64
+	sol_object_t *obj = sol_list_get_index(state, args, 0), *str = CALL_METHOD(state, obj, tostring, args);
65
+	sol_object_t *res = sol_new_buffer(state, strdup(str->str), strlen(str->str), OWN_FREE, NULL, NULL);
66
+	sol_obj_free(obj);
67
+	sol_obj_free(str);
68
+	return res;
69
+}
70
+
62 71
 sol_object_t *sol_f_tbang(sol_state_t *state, sol_object_t *args) {
63 72
 	sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_list_get_index(state, args, 1);
64 73
 	int refa = a->refcnt, refb = b->refcnt;
@@ -100,6 +109,13 @@ sol_object_t *sol_f_tostring(sol_state_t *state, sol_object_t *args) {
100 109
 	return res;
101 110
 }
102 111
 
112
+sol_object_t *sol_f_tobuffer(sol_state_t *state, sol_object_t *args) {
113
+	sol_object_t *obj = sol_list_get_index(state, args, 0);
114
+	sol_object_t *res = CALL_METHOD(state, obj, tobuffer, args);
115
+	sol_obj_free(obj);
116
+	return res;
117
+}
118
+
103 119
 sol_object_t *sol_f_try(sol_state_t *state, sol_object_t *args) {
104 120
 	sol_object_t *func = sol_list_get_index(state, args, 0), *fargs = sol_list_sublist(state, args, 1);
105 121
 	sol_object_t *ls = sol_new_list(state), *one = sol_new_int(state, 1);
@@ -150,7 +166,7 @@ sol_object_t *sol_f_error(sol_state_t *state, sol_object_t *args) {
150 166
 
151 167
 sol_object_t *sol_f_type(sol_state_t *state, sol_object_t *args) {
152 168
 	sol_object_t *obj = sol_list_get_index(state, args, 0);
153
-	sol_object_t *res = sol_new_string(state, obj->ops->tname);
169
+	sol_object_t *res = sol_new_buffer(state, strdup(obj->ops->tname), strlen(obj->ops->tname), OWN_FREE, NULL, NULL);
154 170
 	sol_obj_free(obj);
155 171
 	return res;
156 172
 }
@@ -252,11 +268,14 @@ void ob_print(sol_object_t *obj) {
252 268
 			break;
253 269
 
254 270
 		case SOL_BUFFER:
271
+			/*
255 272
 			if(obj->sz == -1) {
256 273
 				printf("<Buffer @%p>", obj->buffer);
257 274
 			} else {
258 275
 				printf("<Buffer @%p size %ld>", obj->buffer, obj->sz);
259 276
 			}
277
+			*/
278
+			fwrite(obj->buffer, sizeof(char), obj->sz, stdout);
260 279
 			break;
261 280
 
262 281
 		case SOL_CDATA:
@@ -447,7 +466,7 @@ sol_object_t *sol_f_ord(sol_state_t *state, sol_object_t *args) {
447 466
 sol_object_t *sol_f_chr(sol_state_t *state, sol_object_t *args) {
448 467
 	sol_object_t *arg = sol_list_get_index(state, args, 0), *iarg = sol_cast_int(state, arg);
449 468
 	char cbuf[2] = {iarg->ival, 0};
450
-	sol_object_t *res = sol_new_string(state, cbuf);
469
+	sol_object_t *res = sol_new_buffer(state, strdup(cbuf), 1, OWN_FREE, NULL, NULL);
451 470
 	sol_obj_free(arg);
452 471
 	sol_obj_free(iarg);
453 472
 	return res;
@@ -488,6 +507,38 @@ sol_object_t *sol_f_debug_scopes(sol_state_t *state, sol_object_t *args) {
488 507
 	return sol_incref(state->scopes);
489 508
 }
490 509
 
510
+sol_object_t *sol_f_debug_getops(sol_state_t *state, sol_object_t *args) {
511
+	sol_object_t *obj = sol_list_get_index(state, args, 0), *res = sol_new_map(state);
512
+	sol_map_borrow_name(state, res, "add", sol_new_cfunc(state, obj->ops->add, "add"));
513
+	sol_map_borrow_name(state, res, "sub", sol_new_cfunc(state, obj->ops->sub, "sub"));
514
+	sol_map_borrow_name(state, res, "mul", sol_new_cfunc(state, obj->ops->mul, "mul"));
515
+	sol_map_borrow_name(state, res, "div", sol_new_cfunc(state, obj->ops->div, "div"));
516
+	sol_map_borrow_name(state, res, "mod", sol_new_cfunc(state, obj->ops->mod, "mod"));
517
+	sol_map_borrow_name(state, res, "pow", sol_new_cfunc(state, obj->ops->pow, "pow"));
518
+	sol_map_borrow_name(state, res, "tbang", sol_new_cfunc(state, obj->ops->tbang, "tbang"));
519
+	sol_map_borrow_name(state, res, "band", sol_new_cfunc(state, obj->ops->band, "band"));
520
+	sol_map_borrow_name(state, res, "bor", sol_new_cfunc(state, obj->ops->bor, "bor"));
521
+	sol_map_borrow_name(state, res, "bxor", sol_new_cfunc(state, obj->ops->bxor, "bxor"));
522
+	sol_map_borrow_name(state, res, "blsh", sol_new_cfunc(state, obj->ops->blsh, "blsh"));
523
+	sol_map_borrow_name(state, res, "brsh", sol_new_cfunc(state, obj->ops->brsh, "brsh"));
524
+	sol_map_borrow_name(state, res, "bnot", sol_new_cfunc(state, obj->ops->bnot, "bnot"));
525
+	sol_map_borrow_name(state, res, "cmp", sol_new_cfunc(state, obj->ops->cmp, "cmp"));
526
+	sol_map_borrow_name(state, res, "call", sol_new_cfunc(state, obj->ops->call, "call"));
527
+	sol_map_borrow_name(state, res, "index", sol_new_cfunc(state, obj->ops->index, "index"));
528
+	sol_map_borrow_name(state, res, "setindex", sol_new_cfunc(state, obj->ops->setindex, "setindex"));
529
+	sol_map_borrow_name(state, res, "len", sol_new_cfunc(state, obj->ops->len, "len"));
530
+	sol_map_borrow_name(state, res, "iter", sol_new_cfunc(state, obj->ops->iter, "iter"));
531
+	sol_map_borrow_name(state, res, "toint", sol_new_cfunc(state, obj->ops->toint, "toint"));
532
+	sol_map_borrow_name(state, res, "tofloat", sol_new_cfunc(state, obj->ops->tofloat, "tofloat"));
533
+	sol_map_borrow_name(state, res, "tostring", sol_new_cfunc(state, obj->ops->tostring, "tostring"));
534
+	sol_map_borrow_name(state, res, "tobuffer", sol_new_cfunc(state, obj->ops->tobuffer, "tobuffer"));
535
+	sol_map_borrow_name(state, res, "repr", sol_new_cfunc(state, obj->ops->repr, "repr"));
536
+	sol_map_borrow_name(state, res, "init", sol_new_cfunc(state, obj->ops->init, "init"));
537
+	sol_map_borrow_name(state, res, "free", sol_new_cfunc(state, obj->ops->free, "free"));
538
+	sol_obj_free(obj);
539
+	return res;
540
+}
541
+
491 542
 #ifndef NO_READLINE
492 543
 sol_object_t *sol_f_readline_readline(sol_state_t *state, sol_object_t *args) {
493 544
 	sol_object_t *obj, *objstr, *res;
@@ -502,10 +553,10 @@ sol_object_t *sol_f_readline_readline(sol_state_t *state, sol_object_t *args) {
502 553
 		line = readline("");
503 554
 	}
504 555
 	if(line) {
505
-		res = sol_new_string(state, line);
556
+		res = sol_new_buffer(state, strdup(line), strlen(line), OWN_FREE, NULL, NULL);
506 557
 		free(line);
507 558
 	} else {
508
-		res = sol_new_string(state, "");
559
+		res = sol_new_buffer(state, strdup(""), 0, OWN_FREE, NULL, NULL);
509 560
 	}
510 561
 	return res;
511 562
 }
@@ -550,6 +601,31 @@ sol_object_t *sol_f_iter_str(sol_state_t *state, sol_object_t *args) {
550 601
 	return res;
551 602
 }
552 603
 
604
+sol_object_t *sol_f_iter_buffer(sol_state_t *state, sol_object_t *args) {
605
+	sol_object_t *obj = sol_list_get_index(state, args, 0), *local = sol_list_get_index(state, args, 1);
606
+	sol_object_t *idx = sol_map_get_name(state, local, "idx"), *sz = sol_map_get_name(state,local, "sz"), *res;
607
+	if(sol_is_none(state, idx) || sol_is_none(state, sz)) {
608
+		sol_obj_free(idx);
609
+		sol_obj_free(sz);
610
+		idx = sol_new_buffer(state, (void *) 0, sizeof(void *), OWN_NONE, NULL, NULL);
611
+		sz = sol_new_int(state, obj->sz);
612
+		sol_map_set_name(state, local, "idx", idx);
613
+		sol_map_set_name(state, local, "sz", sz);
614
+	}
615
+	if(((size_t) idx->buffer) >= sz->ival) {
616
+		sol_obj_free(idx);
617
+		sol_obj_free(sz);
618
+		sol_obj_free(local);
619
+		return sol_incref(state->None);
620
+	}
621
+	res = sol_new_buffer(state, ((char *) obj->buffer) + ((size_t) idx->buffer), 1, OWN_NONE, NULL, NULL);
622
+	idx->buffer = (void *) ((size_t) idx->buffer + 1);
623
+	sol_obj_free(idx);
624
+	sol_obj_free(sz);
625
+	sol_obj_free(local);
626
+	return res;
627
+}
628
+
553 629
 sol_object_t *sol_f_iter_list(sol_state_t *state, sol_object_t *args) {
554 630
 	sol_object_t *obj = sol_list_get_index(state, args, 0), *local = sol_list_get_index(state, args, 1);
555 631
 	sol_object_t *index = sol_map_get_name(state, local, "idx"), *res;
@@ -611,6 +687,12 @@ sol_object_t *sol_f_singlet_tostring(sol_state_t *state, sol_object_t *args) {
611 687
 	return res;
612 688
 }
613 689
 
690
+sol_object_t *sol_f_singlet_tobuffer(sol_state_t *state, sol_object_t *args) {
691
+	sol_object_t *obj = sol_list_get_index(state, args, 0), *res = sol_new_buffer(state, strdup(obj->str), strlen(obj->str), OWN_FREE, NULL, NULL);
692
+	sol_obj_free(obj);
693
+	return res;
694
+}
695
+
614 696
 sol_object_t *sol_f_int_add(sol_state_t *state, sol_object_t *args) {
615 697
 	sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_list_get_index(state, args, 1), *bint = sol_cast_int(state, b);
616 698
 	sol_object_t *res = sol_new_int(state, a->ival + bint->ival);
@@ -911,7 +993,12 @@ sol_object_t *sol_f_str_mul(sol_state_t *state, sol_object_t *args) {
911 993
 
912 994
 sol_object_t *sol_f_str_cmp(sol_state_t *state, sol_object_t *args) {
913 995
     sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_list_get_index(state, args, 1);
914
-    sol_object_t *res;
996
+    sol_object_t *sb, *res;
997
+	if(sol_is_buffer(b)) {
998
+		sb = sol_cast_string(state, b);
999
+		sol_obj_free(b);
1000
+		b = sb;
1001
+	}
915 1002
 	if(sol_is_string(b)) {
916 1003
 		res = sol_new_int(state, strcmp(a->str, b->str));
917 1004
 	} else {
@@ -970,6 +1057,13 @@ sol_object_t *sol_f_str_tostring(sol_state_t *state, sol_object_t *args) {
970 1057
 	return sol_list_get_index(state, args, 0);
971 1058
 }
972 1059
 
1060
+sol_object_t *sol_f_str_tobuffer(sol_state_t *state, sol_object_t *args) {
1061
+	sol_object_t *str = sol_list_get_index(state, args, 0);
1062
+	sol_object_t *res = sol_new_buffer(state, strdup(str->str), strlen(str->str), OWN_FREE, NULL, NULL);
1063
+	sol_obj_free(str);
1064
+	return res;
1065
+}
1066
+
973 1067
 sol_object_t *sol_f_str_repr(sol_state_t *state, sol_object_t *args) {
974 1068
 	sol_object_t *obj = sol_list_get_index(state, args, 0), *cur = sol_new_string(state, "\""), *next = sol_string_concat(state, cur, obj);
975 1069
 	sol_obj_free(cur);
@@ -1145,7 +1239,7 @@ sol_object_t *sol_f_list_cmp(sol_state_t *state, sol_object_t *args) {
1145 1239
 sol_object_t *sol_f_list_index(sol_state_t *state, sol_object_t *args) {
1146 1240
 	sol_object_t *ls = sol_list_get_index(state, args, 0), *b = sol_list_get_index(state, args, 1), *ival;
1147 1241
 	sol_object_t *res, *funcs;
1148
-	if(sol_is_string(b)) {
1242
+	if(sol_is_name(b)) {
1149 1243
 		funcs = sol_get_methods_name(state, "list");
1150 1244
 		res = sol_map_get(state, funcs, b);
1151 1245
 		sol_obj_free(funcs);
@@ -1515,35 +1609,35 @@ sol_object_t *sol_f_func_index(sol_state_t *state, sol_object_t *args) {
1515 1609
 	sol_object_t *func = sol_list_get_index(state, args, 0), *key = sol_list_get_index(state, args, 1), *res;
1516 1610
 	identlist_node *curi;
1517 1611
 	int i = 0;
1518
-	if(!sol_is_string(key)) {
1612
+	if(!sol_is_name(key)) {
1519 1613
 		res = sol_map_get(state, func->udata, key);
1520 1614
 	} else {
1521
-		if(sol_string_eq(state, key, "name")) {
1615
+		if(sol_name_eq(state, key, "name")) {
1522 1616
 			if(func->fname) {
1523 1617
 				res = sol_new_string(state, func->fname);
1524 1618
 			} else {
1525 1619
 				res = sol_incref(state->None);
1526 1620
 			}
1527
-		} else if(sol_string_eq(state, key, "closure")) {
1621
+		} else if(sol_name_eq(state, key, "closure")) {
1528 1622
 			res = sol_incref(func->closure);
1529
-		} else if(sol_string_eq(state, key, "udata")) {
1623
+		} else if(sol_name_eq(state, key, "udata")) {
1530 1624
 			res = sol_incref(func->udata);
1531
-		} else if(sol_string_eq(state, key, "stmt")) {
1625
+		} else if(sol_name_eq(state, key, "stmt")) {
1532 1626
 			res = sol_new_stmtnode(state, st_copy((stmt_node *) func->func));
1533
-		} else if(sol_string_eq(state, key, "args")) {
1627
+		} else if(sol_name_eq(state, key, "args")) {
1534 1628
 			res = sol_new_list(state);
1535 1629
 			curi = func->args;
1536 1630
 			while(curi) {
1537 1631
 				sol_list_insert(state, res, i++, sol_new_string(state, curi->ident));
1538 1632
 				curi = curi->next;
1539 1633
 			}
1540
-		} else if(sol_string_eq(state, key, "rest")) {
1634
+		} else if(sol_name_eq(state, key, "rest")) {
1541 1635
 			if(func->rest) {
1542 1636
 				res = sol_new_string(state, func->rest);
1543 1637
 			} else {
1544 1638
 				res = sol_incref(state->None);
1545 1639
 			}
1546
-		} else if(sol_string_eq(state, key, "annos")) {
1640
+		} else if(sol_name_eq(state, key, "annos")) {
1547 1641
 			res = sol_incref(func->annos);
1548 1642
 		} else {
1549 1643
 			res = sol_map_get(state, func->udata, key);
@@ -1558,21 +1652,25 @@ sol_object_t *sol_f_func_setindex(sol_state_t *state, sol_object_t *args) {
1558 1652
 	sol_object_t *func = sol_list_get_index(state, args, 0), *key = sol_list_get_index(state, args, 1), *val = sol_list_get_index(state, args, 2), *temp, *str;
1559 1653
 	size_t i, len;
1560 1654
 	identlist_node *cur, *prev;
1561
-	if(sol_string_eq(state, key, "name") && sol_is_string(val)) {
1655
+	if(sol_name_eq(state, key, "name") && sol_is_name(val)) {
1562 1656
 		free(func->fname);
1563
-		func->fname = strdup(val->str);
1564
-	} else if(sol_string_eq(state, key, "closure") && sol_is_map(val)) {
1657
+		if(sol_is_string(val)) {
1658
+			func->fname = strdup(val->str);
1659
+		} else {
1660
+			func->fname = sol_buffer_strdup(val);
1661
+		}
1662
+	} else if(sol_name_eq(state, key, "closure") && sol_is_map(val)) {
1565 1663
 		temp = func->closure;
1566 1664
 		func->closure = sol_incref(val);
1567 1665
 		sol_obj_free(temp);
1568
-	} else if(sol_string_eq(state, key, "udata") && sol_is_map(val)) {
1666
+	} else if(sol_name_eq(state, key, "udata") && sol_is_map(val)) {
1569 1667
 		temp = func->udata;
1570 1668
 		func->udata = sol_incref(val);
1571 1669
 		sol_obj_free(temp);
1572
-	} else if(sol_string_eq(state, key, "stmt") && sol_is_aststmt(val)) {
1670
+	} else if(sol_name_eq(state, key, "stmt") && sol_is_aststmt(val)) {
1573 1671
 		st_free(func->func);
1574 1672
 		func->func = st_copy(val->node);
1575
-	} else if(sol_string_eq(state, key, "args") && sol_is_list(val)) {
1673
+	} else if(sol_name_eq(state, key, "args") && sol_is_list(val)) {
1576 1674
 		idl_free(func->args);
1577 1675
 		func->args = NEW(identlist_node);
1578 1676
 		cur = func->args;
@@ -1591,10 +1689,14 @@ sol_object_t *sol_f_func_setindex(sol_state_t *state, sol_object_t *args) {
1591 1689
 		prev->next = NULL;
1592 1690
 		if(cur == func->args) func->args = NULL;
1593 1691
 		free(cur);
1594
-	} else if(sol_string_eq(state, key, "rest") && sol_is_string(val)) {
1692
+	} else if(sol_name_eq(state, key, "rest") && sol_is_name(val)) {
1595 1693
 		free(func->rest);
1596
-		func->rest = strdup(val->str);
1597
-	} else if(sol_string_eq(state, key, "annos") && sol_is_map(val)) {
1694
+		if(sol_is_string(val)) {
1695
+			func->rest = strdup(val->str);
1696
+		} else {
1697
+			func->rest = sol_buffer_strdup(val);
1698
+		}
1699
+	} else if(sol_name_eq(state, key, "annos") && sol_is_map(val)) {
1598 1700
 		sol_obj_free(func->annos);
1599 1701
 		func->annos = sol_incref(val);
1600 1702
 	} else {
@@ -2307,26 +2409,158 @@ sol_object_t *sol_f_astnode_tostring(sol_state_t *state, sol_object_t *args) {
2307 2409
 }
2308 2410
 
2309 2411
 sol_object_t *sol_f_buffer_index(sol_state_t *state, sol_object_t *args) {
2412
+	sol_object_t *a = sol_list_get_index(state, args, 0);
2310 2413
 	sol_object_t *key = sol_list_get_index(state, args, 1), *funcs = sol_get_methods_name(state, "buffer");
2311
-	sol_object_t *res = sol_map_get(state, funcs, key);
2414
+	sol_object_t *res;
2415
+	if(sol_is_name(key)) {
2416
+		res = sol_map_get(state, funcs, key);
2417
+	} else if(sol_is_int(key)) {
2418
+		res = sol_new_buffer(state, a->buffer, (a->sz < 0) ? a->sz : (a->sz - key->ival), OWN_NONE, NULL, NULL);
2419
+	} else {
2420
+		res = sol_f_not_impl(state, args);
2421
+	}
2422
+	sol_obj_free(a);
2312 2423
 	sol_obj_free(key);
2313 2424
 	sol_obj_free(funcs);
2314 2425
 	return res;
2315 2426
 }
2316 2427
 
2428
+sol_object_t *sol_f_buffer_add(sol_state_t *state, sol_object_t *args) {
2429
+	sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_list_get_index(state, args, 1), *bb = sol_cast_buffer(state, b);
2430
+	sol_object_t *res = sol_buffer_concat(state, a, bb);
2431
+	sol_obj_free(a);
2432
+	sol_obj_free(b);
2433
+	if(sol_has_error(state)) {
2434
+		sol_obj_free(res);
2435
+		return sol_incref(state->None);
2436
+	}
2437
+	return res;
2438
+}
2439
+
2440
+sol_object_t *sol_f_buffer_mul(sol_state_t *state, sol_object_t *args) {
2441
+	sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_list_get_index(state, args, 1), *bint = sol_cast_int(state, b);
2442
+	long ival, i;
2443
+	size_t sz;
2444
+	char *buf;
2445
+	sol_obj_free(b);
2446
+	if(sol_has_error(state)) {
2447
+		sol_obj_free(a);
2448
+		sol_obj_free(bint);
2449
+		return sol_incref(state->None);
2450
+	}
2451
+	ival = bint->ival;
2452
+	sol_obj_free(bint);
2453
+	if(a->sz < 0) {
2454
+		sol_obj_free(a);
2455
+		return sol_set_error_string(state, "Multiply unsized buffer");
2456
+	}
2457
+	if(ival < 0) {
2458
+		ival = 0;
2459
+	}
2460
+	sz = a->sz * ival;
2461
+	buf = malloc(sz * sizeof(char));
2462
+	for(i = 0; i < ival; i++) {
2463
+		memcpy(buf + (i * a->sz), a->buffer, a->sz);
2464
+	}
2465
+	sol_obj_free(a);
2466
+	return sol_new_buffer(state, buf, sz, OWN_FREE, NULL, NULL);
2467
+}
2468
+
2469
+sol_object_t *sol_f_buffer_cmp(sol_state_t *state, sol_object_t *args) {
2470
+	sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_list_get_index(state, args, 1);
2471
+	sol_object_t *bb, *res;
2472
+	if(sol_is_string(b)) {
2473
+		bb = sol_cast_buffer(state, b);
2474
+		sol_obj_free(b);
2475
+		b = bb;
2476
+	}
2477
+	if(sol_is_buffer(b)) {
2478
+		ssize_t len = a->sz;
2479
+		if(a->sz >= 0 && b->sz >= 0 && a->sz != b->sz) {
2480
+			res = sol_new_int(state, 1);
2481
+		} else {
2482
+			if(len < 0) {
2483
+				len = b->sz;
2484
+			}
2485
+			if(a->sz >= 0 && len > a->sz) len = a->sz;
2486
+			if(b->sz >= 0 && len > b->sz) len = b->sz;
2487
+			if(len < 0) {
2488
+				res = sol_new_int(state, 1);
2489
+			} else {
2490
+				res = sol_new_int(state, memcmp(a->buffer, b->buffer, len));
2491
+			}
2492
+		}
2493
+	} else {
2494
+		res = sol_new_int(state, 1);
2495
+	}
2496
+	sol_obj_free(a);
2497
+	sol_obj_free(b);
2498
+	return res;
2499
+}
2500
+
2501
+sol_object_t *sol_f_buffer_len(sol_state_t *state, sol_object_t *args) {
2502
+	sol_object_t *a = sol_list_get_index(state, args, 0);
2503
+	sol_object_t *res = sol_new_int(state, a->sz);
2504
+	sol_obj_free(a);
2505
+	return res;
2506
+}
2507
+
2508
+sol_object_t *sol_f_buffer_iter(sol_state_t *state, sol_object_t *args) {
2509
+	return sol_new_cfunc(state, sol_f_iter_buffer, "iter.buffer");
2510
+}
2511
+
2317 2512
 sol_object_t *sol_f_buffer_tostring(sol_state_t *state, sol_object_t *args) {
2318 2513
 	sol_object_t *buf = sol_list_get_index(state, args, 0), *res;
2514
+	char *b;
2515
+	/*
2319 2516
 	char s[64];
2320 2517
 	if(buf->sz == -1) {
2321 2518
 		snprintf(s, 64, "<Buffer @%p>", buf->buffer);
2322 2519
 	} else {
2323
-		snprintf(s, 64, "<Buffer @%p size %ld", buf->buffer, buf->sz);
2520
+		snprintf(s, 64, "<Buffer @%p size %ld>", buf->buffer, buf->sz);
2521
+	}
2522
+	*/
2523
+	if(buf->sz < 0) {
2524
+		res = sol_new_string(state, "<UNSIZED_BUFFER>");
2525
+	} else {
2526
+		b = malloc(buf->sz + 1);
2527
+		strncpy(b, buf->buffer, buf->sz);
2528
+		b[buf->sz] = '\0';
2529
+		res = sol_new_string(state, b);
2530
+		free(b);
2324 2531
 	}
2325
-	res = sol_new_string(state, s);
2326 2532
 	sol_obj_free(buf);
2327 2533
 	return res;
2328 2534
 }
2329 2535
 
2536
+sol_object_t *sol_f_buffer_repr(sol_state_t *state, sol_object_t *args) {
2537
+	sol_object_t *obj = sol_list_get_index(state, args, 0), *cur = sol_new_buffer(state, "'", 1, OWN_NONE, NULL, NULL), *next = sol_buffer_concat(state, cur, obj);
2538
+	sol_object_t *termin = sol_new_buffer(state, "'", 2, OWN_NONE, NULL, NULL);
2539
+	sol_obj_free(cur);
2540
+	cur = next;
2541
+	next = sol_buffer_concat(state, cur, termin);
2542
+	sol_obj_free(cur);
2543
+	return next;
2544
+}
2545
+
2546
+sol_object_t *sol_f_buffer_toint(sol_state_t *state, sol_object_t *args) {
2547
+	sol_object_t *a = sol_list_get_index(state, args, 0);
2548
+	sol_object_t *res = sol_new_int(state, atoi(a->buffer));
2549
+	sol_obj_free(a);
2550
+	return res;
2551
+}
2552
+
2553
+sol_object_t *sol_f_buffer_tofloat(sol_state_t *state, sol_object_t *args) {
2554
+	sol_object_t *a = sol_list_get_index(state, args, 0);
2555
+	sol_object_t *res = sol_new_float(state, atof(a->buffer));
2556
+	sol_obj_free(a);
2557
+	return res;
2558
+}
2559
+
2560
+sol_object_t *sol_f_buffer_tobuffer(sol_state_t *state, sol_object_t *args) {
2561
+	return sol_list_get_index(state, args, 0);
2562
+}
2563
+
2330 2564
 sol_object_t *sol_f_buffer_new(sol_state_t *state, sol_object_t *args) {
2331 2565
 	sol_object_t *sz = sol_list_get_index(state, args, 0), *isz = sol_cast_int(state, sz);
2332 2566
 	size_t bufsz = isz->ival;
@@ -2585,6 +2819,97 @@ sol_object_t *sol_f_buffer_size(sol_state_t *state, sol_object_t *args) {
2585 2819
 	return res;
2586 2820
 }
2587 2821
 
2822
+sol_object_t *sol_f_buffer_sub(sol_state_t *state, sol_object_t *args) {
2823
+	sol_object_t *buf = sol_list_get_index(state, args, 0);
2824
+	sol_object_t *low = sol_list_get_index(state, args, 1), *high = sol_list_get_index(state, args, 2);
2825
+	sol_object_t *ilow, *ihigh;
2826
+	long l, h;
2827
+	char *b;
2828
+	if(sol_is_none(state, low)) {
2829
+		ilow = sol_new_int(state, 0);
2830
+	} else {
2831
+		ilow = sol_cast_int(state, low);
2832
+	}
2833
+	if(sol_is_none(state, high)) {
2834
+		ihigh = sol_new_int(state, buf->sz);
2835
+	} else {
2836
+		ihigh = sol_cast_int(state, high);
2837
+	}
2838
+	l = ilow->ival;
2839
+	h = ihigh->ival;
2840
+	sol_obj_free(low);
2841
+	sol_obj_free(high);
2842
+	sol_obj_free(ilow);
2843
+	sol_obj_free(ihigh);
2844
+	if(l < 0) {
2845
+		l += buf->sz;
2846
+		if(l < 0) {
2847
+			l = 0;
2848
+		}
2849
+	}
2850
+	if(l > buf->sz) {
2851
+		l = buf->sz;
2852
+	}
2853
+	if(h < 0) {
2854
+		h += buf->sz;
2855
+		if(h < 0) {
2856
+			h = 0;
2857
+		}
2858
+	}
2859
+	if(h > buf->sz) {
2860
+		h = buf->sz;
2861
+	}
2862
+	if(l >= h) {
2863
+		sol_obj_free(buf);
2864
+		return sol_new_buffer(state, NULL, 0, OWN_NONE, NULL, NULL);
2865
+	}
2866
+	b = malloc(sizeof(char) * (h - l));
2867
+	memcpy(b, buf->buffer, h - l);
2868
+	sol_obj_free(buf);
2869
+	return sol_new_buffer(state, b, h - l, OWN_FREE, NULL, NULL);
2870
+}
2871
+
2872
+sol_object_t *sol_f_buffer_split(sol_state_t *state, sol_object_t *args) {
2873
+	sol_object_t *buf = sol_list_get_index(state, args, 0);
2874
+	char *b;
2875
+	sol_object_t *str, *res, *ls;
2876
+	if(buf->sz < 0) {
2877
+		sol_obj_free(buf);
2878
+		return sol_set_error_string(state, "split unsized buffer");
2879
+	}
2880
+	b = malloc(sizeof(char) * (buf->sz + 1));
2881
+	memcpy(b, buf->buffer, buf->sz);
2882
+	b[buf->sz] = '\0';
2883
+	str = sol_new_string(state, b);
2884
+	free(b);
2885
+	ls = sol_new_list(state);
2886
+	sol_list_insert(state, ls, 0, str);
2887
+	sol_obj_free(str);
2888
+	str = sol_list_get_index(state, args, 1);
2889
+	sol_list_insert(state, ls, 1, str);
2890
+	sol_obj_free(str);
2891
+	res = sol_f_str_split(state, ls);
2892
+	sol_obj_free(ls);
2893
+	return res;
2894
+}
2895
+
2896
+sol_object_t *sol_f_buffer_find(sol_state_t *state, sol_object_t *args) {
2897
+	sol_object_t *buf = sol_list_get_index(state, args, 0), *subbuf = sol_list_get_index(state, args, 1), *bsubbuf = sol_cast_buffer(state, subbuf);
2898
+	sol_object_t *res;
2899
+	char *ptr;
2900
+	sol_obj_free(subbuf);
2901
+	if(buf->sz < 0 || bsubbuf->sz < 0) {
2902
+		sol_obj_free(buf);
2903
+		sol_obj_free(bsubbuf);
2904
+		return sol_set_error_string(state, "find with unsized buffer");
2905
+	}
2906
+	ptr = memmem(buf->buffer, buf->sz, bsubbuf->buffer, bsubbuf->sz);
2907
+	res = sol_new_int(state, ptr ? (ptr - ((char *) buf->buffer)) : -1);
2908
+	sol_obj_free(buf);
2909
+	sol_obj_free(bsubbuf);
2910
+	return res;
2911
+}
2912
+
2588 2913
 sol_object_t *sol_f_buffer_fromstring(sol_state_t *state, sol_object_t *args) {
2589 2914
 	sol_object_t *val = sol_list_get_index(state, args, 0), *sval = sol_cast_string(state, val);
2590 2915
 	size_t sz = strlen(sval->str) + 1;
@@ -2654,7 +2979,7 @@ sol_object_t *sol_f_stream_blsh(sol_state_t *state, sol_object_t *args) {
2654 2979
 }
2655 2980
 
2656 2981
 sol_object_t *sol_f_stream_brsh(sol_state_t *state, sol_object_t *args) {
2657
-	return sol_f_stream_read(state, args);
2982
+	return sol_f_stream_read_buffer(state, args);
2658 2983
 }
2659 2984
 
2660 2985
 sol_object_t *sol_f_stream_index(sol_state_t *state, sol_object_t *args) {
@@ -2670,10 +2995,16 @@ sol_object_t *sol_f_stream_tostring(sol_state_t *state, sol_object_t *args) {
2670 2995
 }
2671 2996
 
2672 2997
 sol_object_t *sol_f_stream_write(sol_state_t *state, sol_object_t *args) {
2673
-	sol_object_t *stream = sol_list_get_index(state, args, 0), *obj = sol_list_get_index(state, args, 1), *str = sol_cast_string(state, obj);
2674
-	size_t sz = sol_stream_printf(state, stream, "%s", str->str);
2998
+	sol_object_t *stream = sol_list_get_index(state, args, 0), *obj = sol_list_get_index(state, args, 1), *str;
2999
+	size_t sz;
3000
+	if(sol_is_buffer(obj)) {
3001
+		sz = sol_stream_fwrite(state, stream, obj->buffer, sizeof(char), obj->sz);
3002
+	} else {
3003
+		str = sol_cast_string(state, obj);
3004
+		sz = sol_stream_printf(state, stream, "%s", str->str);
3005
+		sol_obj_free(str);
3006
+	}
2675 3007
 	sol_obj_free(obj);
2676
-	sol_obj_free(str);
2677 3008
 	sol_obj_free(stream);
2678 3009
 	return sol_new_int(state, sz);
2679 3010
 }
@@ -2682,8 +3013,8 @@ sol_object_t *sol_f_stream_read_buffer(sol_state_t *state, sol_object_t *args) {
2682 3013
 	sol_object_t *stream = sol_list_get_index(state, args, 0), *amt = sol_list_get_index(state, args, 1), *iamt, *res;
2683 3014
 	char *s = NULL, *p;
2684 3015
 	size_t count = 0, max = 0, pos, end;
2685
-	if(sol_is_string(amt)) {
2686
-		if(sol_string_eq(state, amt, "ALL")) {
3016
+	if(sol_is_name(amt)) {
3017
+		if(sol_name_eq(state, amt, "ALL")) {
2687 3018
 			pos = sol_stream_ftell(state, stream);
2688 3019
 			sol_stream_fseek(state, stream, 0, SEEK_END);
2689 3020
 			end = sol_stream_ftell(state, stream);
@@ -2697,7 +3028,7 @@ sol_object_t *sol_f_stream_read_buffer(sol_state_t *state, sol_object_t *args) {
2697 3028
 				return sol_set_error_string(state, "IO read error");
2698 3029
 			}
2699 3030
 			count = end - pos;
2700
-		} else if(sol_string_eq(state, amt, "LINE")) {
3031
+		} else if(sol_name_eq(state, amt, "LINE")) {
2701 3032
 			s = malloc(STDIO_CHUNK_SIZE * sizeof(char));
2702 3033
 			sol_stream_fgets(state, stream, s, STDIO_CHUNK_SIZE);
2703 3034
 			count = strlen(s);
@@ -2720,12 +3051,14 @@ sol_object_t *sol_f_stream_read_buffer(sol_state_t *state, sol_object_t *args) {
2720 3051
 	return res;
2721 3052
 }
2722 3053
 
3054
+/*
2723 3055
 sol_object_t *sol_f_stream_read(sol_state_t *state, sol_object_t *args) {
2724 3056
 	sol_object_t *buf = sol_f_stream_read_buffer(state, args);
2725 3057
 	sol_object_t *str = sol_new_string(state, buf->buffer);
2726 3058
 	sol_obj_free(buf);
2727 3059
 	return str;
2728 3060
 }
3061
+*/
2729 3062
 
2730 3063
 sol_object_t *sol_f_stream_seek(sol_state_t *state, sol_object_t *args) {
2731 3064
 	sol_object_t *stream = sol_list_get_index(state, args, 0), *offset = sol_list_get_index(state, args, 1), *whence = sol_list_get_index(state, args, 2);

+ 141
- 196
lex.yy.c View File

@@ -8,96 +8,34 @@
8 8
 #define FLEX_SCANNER
9 9
 #define YY_FLEX_MAJOR_VERSION 2
10 10
 #define YY_FLEX_MINOR_VERSION 6
11
-#define YY_FLEX_SUBMINOR_VERSION 3
11
+#define YY_FLEX_SUBMINOR_VERSION 4
12 12
 #if YY_FLEX_SUBMINOR_VERSION > 0
13 13
 #define FLEX_BETA
14 14
 #endif
15 15
 
16
-    #define yy_create_buffer yy_create_buffer
17
-
18
-    #define yy_delete_buffer yy_delete_buffer
19
-
20
-    #define yy_scan_buffer yy_scan_buffer
21
-
22
-    #define yy_scan_string yy_scan_string
23
-
24
-    #define yy_scan_bytes yy_scan_bytes
25
-
26
-    #define yy_init_buffer yy_init_buffer
27
-
28
-    #define yy_flush_buffer yy_flush_buffer
29
-
30
-    #define yy_load_buffer_state yy_load_buffer_state
31
-
32
-    #define yy_switch_to_buffer yy_switch_to_buffer
33
-
34
-    #define yypush_buffer_state yypush_buffer_state
35
-
36
-    #define yypop_buffer_state yypop_buffer_state
37
-
38
-    #define yyensure_buffer_stack yyensure_buffer_stack
39
-
40
-    #define yylex yylex
41
-
42
-    #define yyrestart yyrestart
43
-
44
-    #define yylex_init yylex_init
45
-
46
-    #define yylex_init_extra yylex_init_extra
47
-
48
-    #define yylex_destroy yylex_destroy
49
-
50
-    #define yyget_debug yyget_debug
51
-
52
-    #define yyset_debug yyset_debug
53
-
54
-    #define yyget_extra yyget_extra
55
-
56
-    #define yyset_extra yyset_extra
57
-
58
-    #define yyget_in yyget_in
59
-
60
-    #define yyset_in yyset_in
61
-
62
-    #define yyget_out yyget_out
63
-
64
-    #define yyset_out yyset_out
65
-
66
-    #define yyget_leng yyget_leng
67
-
68
-    #define yyget_text yyget_text
69
-
70
-    #define yyget_lineno yyget_lineno
71
-
72
-    #define yyset_lineno yyset_lineno
73
-
74
-    #define yywrap yywrap
75
-
76
-    #define yyget_lval yyget_lval
77
-
78
-    #define yyset_lval yyset_lval
79
-
80
-    #define yyget_lloc yyget_lloc
81
-
82
-    #define yyset_lloc yyset_lloc
83
-
84
-    #define yyalloc yyalloc
85
-
86
-    #define yyrealloc yyrealloc
87
-
88
-    #define yyfree yyfree
89
-
90
-    #define yytext yytext
91
-
92
-    #define yyleng yyleng
93
-
94
-    #define yyin yyin
16
+#ifdef yyget_lval
17
+#define yyget_lval_ALREADY_DEFINED
18
+#else
19
+#define yyget_lval yyget_lval
20
+#endif
95 21
 
96
-    #define yyout yyout
22
+#ifdef yyset_lval
23
+#define yyset_lval_ALREADY_DEFINED
24
+#else
25
+#define yyset_lval yyset_lval
26
+#endif
97 27
 
98
-    #define yy_flex_debug yy_flex_debug
28
+#ifdef yyget_lloc
29
+#define yyget_lloc_ALREADY_DEFINED
30
+#else
31
+#define yyget_lloc yyget_lloc
32
+#endif
99 33
 
100
-    #define yylineno yylineno
34
+#ifdef yyset_lloc
35
+#define yyset_lloc_ALREADY_DEFINED
36
+#else
37
+#define yyset_lloc yyset_lloc
38
+#endif
101 39
 
102 40
 /* First, we deal with  platform-specific or compiler-specific issues. */
103 41
 
@@ -169,10 +107,16 @@ typedef unsigned int flex_uint32_t;
169 107
 #define UINT32_MAX             (4294967295U)
170 108
 #endif
171 109
 
110
+#ifndef SIZE_MAX
111
+#define SIZE_MAX               (~(size_t)0)
112
+#endif
113
+
172 114
 #endif /* ! C99 */
173 115
 
174 116
 #endif /* ! FLEXINT_H */
175 117
 
118
+/* begin standard C++ headers. */
119
+
176 120
 /* TODO: this is always defined, so inline it */
177 121
 #define yyconst const
178 122
 
@@ -204,7 +148,7 @@ typedef unsigned int flex_uint32_t;
204 148
 /* Action number for EOF rule of a given start state. */
205 149
 #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
206 150
 /* Special action meaning "start processing a new file". */
207
-#define YY_NEW_FILE yyrestart(yyin  )
151
+#define YY_NEW_FILE yyrestart( yyin  )
208 152
 #define YY_END_OF_BUFFER_CHAR 0
209 153
 
210 154
 /* Size of default input buffer. */
@@ -370,7 +314,7 @@ void yypop_buffer_state ( void );
370 314
 static void yyensure_buffer_stack ( void );
371 315
 static void yy_load_buffer_state ( void );
372 316
 static void yy_init_buffer ( YY_BUFFER_STATE b, FILE *file  );
373
-#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER )
317
+#define YY_FLUSH_BUFFER yy_flush_buffer( YY_CURRENT_BUFFER )
374 318
 
375 319
 YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size  );
376 320
 YY_BUFFER_STATE yy_scan_string ( const char *yy_str  );
@@ -386,7 +330,7 @@ void yyfree ( void *  );
386 330
 	if ( ! YY_CURRENT_BUFFER ){ \
387 331
         yyensure_buffer_stack (); \
388 332
 		YY_CURRENT_BUFFER_LVALUE =    \
389
-            yy_create_buffer(yyin,YY_BUF_SIZE ); \
333
+            yy_create_buffer( yyin, YY_BUF_SIZE ); \
390 334
 	} \
391 335
 	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
392 336
 	}
@@ -395,7 +339,7 @@ void yyfree ( void *  );
395 339
 	if ( ! YY_CURRENT_BUFFER ){\
396 340
         yyensure_buffer_stack (); \
397 341
 		YY_CURRENT_BUFFER_LVALUE =    \
398
-            yy_create_buffer(yyin,YY_BUF_SIZE ); \
342
+            yy_create_buffer( yyin, YY_BUF_SIZE ); \
399 343
 	} \
400 344
 	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
401 345
 	}
@@ -677,7 +621,7 @@ static void update_loc(YYLTYPE *yylloc, char *yytext){
677 621
 
678 622
 #define YY_USER_ACTION update_loc(yylloc, yytext);
679 623
 
680
-#line 680 "lex.yy.c"
624
+#line 624 "lex.yy.c"
681 625
 /* This is the right way to do it, but it keeps generating token $undefined.
682 626
 
683 627
 %x STRING
@@ -693,7 +637,7 @@ static void update_loc(YYLTYPE *yylloc, char *yytext){
693 637
 <STRING>. { str_putc(*yytext); }
694 638
 
695 639
 */
696
-#line 696 "lex.yy.c"
640
+#line 640 "lex.yy.c"
697 641
 
698 642
 #define INITIAL 0
699 643
 
@@ -924,17 +868,17 @@ YY_DECL
924 868
 		if ( ! YY_CURRENT_BUFFER ) {
925 869
 			yyensure_buffer_stack ();
926 870
 			YY_CURRENT_BUFFER_LVALUE =
927
-				yy_create_buffer(yyin,YY_BUF_SIZE );
871
+				yy_create_buffer( yyin, YY_BUF_SIZE );
928 872
 		}
929 873
 
930
-		yy_load_buffer_state( );
874
+		yy_load_buffer_state(  );
931 875
 		}
932 876
 
933 877
 	{
934 878
 #line 85 "tokenizer.lex"
935 879
 
936 880
 
937
-#line 937 "lex.yy.c"
881
+#line 881 "lex.yy.c"
938 882
 
939 883
 	while ( /*CONSTCOND*/1 )		/* loops until end-of-file is reached */
940 884
 		{
@@ -1004,369 +948,366 @@ YY_RULE_SETUP
1004 948
 	YY_BREAK
1005 949
 case 3:
1006 950
 /* rule 3 can match eol */
1007
-YY_RULE_SETUP
1008
-#line 91 "tokenizer.lex"
1009
-{ *yylval = strdup(yytext+1); ((char *) *yylval)[yyleng-2] = 0; return STRING; }
1010
-	YY_BREAK
951
+#line 92 "tokenizer.lex"
1011 952
 case 4:
1012 953
 /* rule 4 can match eol */
1013 954
 YY_RULE_SETUP
1014
-#line 93 "tokenizer.lex"
1015
-{ *yylval = strdup(yytext+1); ((char *) *yylval)[yyleng-2] = 0; return STRING; }
955
+#line 92 "tokenizer.lex"
956
+{ *yylval = malloc(sizeof(unsigned long) + (yyleng - 2) * sizeof(char)); *((unsigned long *) *yylval) = yyleng - 2; memcpy(((char *) *yylval) + sizeof(unsigned long), yytext + 1, yyleng - 2); return STRING; }
1016 957
 	YY_BREAK
1017 958
 case 5:
1018 959
 YY_RULE_SETUP
1019
-#line 95 "tokenizer.lex"
960
+#line 94 "tokenizer.lex"
1020 961
 { return IF; }
1021 962
 	YY_BREAK
1022 963
 case 6:
1023 964
 YY_RULE_SETUP
1024
-#line 97 "tokenizer.lex"
965
+#line 96 "tokenizer.lex"
1025 966
 { return THEN; }
1026 967
 	YY_BREAK
1027 968
 case 7:
1028 969
 YY_RULE_SETUP
1029
-#line 99 "tokenizer.lex"
970
+#line 98 "tokenizer.lex"
1030 971
 { return ELSE; }
1031 972
 	YY_BREAK
1032 973
 case 8:
1033 974
 YY_RULE_SETUP
1034
-#line 101 "tokenizer.lex"
975
+#line 100 "tokenizer.lex"
1035 976
 { return ELSEIF; }
1036 977
 	YY_BREAK
1037 978
 case 9:
1038 979
 YY_RULE_SETUP
1039
-#line 103 "tokenizer.lex"
980
+#line 102 "tokenizer.lex"
1040 981
 { return WHILE; }
1041 982
 	YY_BREAK
1042 983
 case 10:
1043 984
 YY_RULE_SETUP
1044
-#line 105 "tokenizer.lex"
985
+#line 104 "tokenizer.lex"
1045 986
 { return FOR; }
1046 987
 	YY_BREAK
1047 988
 case 11:
1048 989
 YY_RULE_SETUP
1049
-#line 107 "tokenizer.lex"
990
+#line 106 "tokenizer.lex"
1050 991
 { return IN; }
1051 992
 	YY_BREAK
1052 993
 case 12:
1053 994
 YY_RULE_SETUP
1054
-#line 109 "tokenizer.lex"
995
+#line 108 "tokenizer.lex"
1055 996
 { return DO; }
1056 997
 	YY_BREAK
1057 998
 case 13:
1058 999
 YY_RULE_SETUP
1059
-#line 111 "tokenizer.lex"
1000
+#line 110 "tokenizer.lex"
1060 1001
 { return FUNC; }
1061 1002
 	YY_BREAK
1062 1003
 case 14:
1063 1004
 YY_RULE_SETUP
1064
-#line 113 "tokenizer.lex"
1005
+#line 112 "tokenizer.lex"
1065 1006
 { return LAMBDA; }
1066 1007
 	YY_BREAK
1067 1008
 case 15:
1068 1009
 YY_RULE_SETUP
1069
-#line 115 "tokenizer.lex"
1010
+#line 114 "tokenizer.lex"
1070 1011
 { return RETURN; }
1071 1012
 	YY_BREAK
1072 1013
 case 16:
1073 1014
 YY_RULE_SETUP
1074
-#line 117 "tokenizer.lex"
1015
+#line 116 "tokenizer.lex"
1075 1016
 { return BREAK; }
1076 1017
 	YY_BREAK
1077 1018
 case 17:
1078 1019
 YY_RULE_SETUP
1079
-#line 119 "tokenizer.lex"
1020
+#line 118 "tokenizer.lex"
1080 1021
 { return CONTINUE; }
1081 1022
 	YY_BREAK
1082 1023
 case 18:
1083 1024
 YY_RULE_SETUP
1084
-#line 121 "tokenizer.lex"
1025
+#line 120 "tokenizer.lex"
1085 1026
 { return END; }
1086 1027
 	YY_BREAK
1087 1028
 case 19:
1088 1029
 YY_RULE_SETUP
1089
-#line 123 "tokenizer.lex"
1030
+#line 122 "tokenizer.lex"
1090 1031
 { return NONE; }
1091 1032
 	YY_BREAK
1092 1033
 case 20:
1093 1034
 YY_RULE_SETUP
1094
-#line 125 "tokenizer.lex"
1035
+#line 124 "tokenizer.lex"
1095 1036
 { return PLUS; }
1096 1037
 	YY_BREAK
1097 1038
 case 21:
1098 1039
 YY_RULE_SETUP
1099
-#line 127 "tokenizer.lex"
1040
+#line 126 "tokenizer.lex"
1100 1041
 { return MINUS; }
1101 1042
 	YY_BREAK
1102 1043
 case 22:
1103 1044
 YY_RULE_SETUP
1104
-#line 129 "tokenizer.lex"
1045
+#line 128 "tokenizer.lex"
1105 1046
 { return STAR; }
1106 1047
 	YY_BREAK
1107 1048
 case 23:
1108 1049
 YY_RULE_SETUP
1109
-#line 131 "tokenizer.lex"
1050
+#line 130 "tokenizer.lex"
1110 1051
 { return SLASH; }
1111 1052
 	YY_BREAK
1112 1053
 case 24:
1113 1054
 YY_RULE_SETUP
1114
-#line 133 "tokenizer.lex"
1055
+#line 132 "tokenizer.lex"
1115 1056
 { return PERCENT; }
1116 1057
 	YY_BREAK
1117 1058
 case 25:
1118 1059
 YY_RULE_SETUP
1119
-#line 135 "tokenizer.lex"
1060
+#line 134 "tokenizer.lex"
1120 1061
 { return PERCENT; }
1121 1062
 	YY_BREAK
1122 1063
 case 26:
1123 1064
 YY_RULE_SETUP
1124
-#line 137 "tokenizer.lex"
1065
+#line 136 "tokenizer.lex"
1125 1066
 { return DSTAR; }
1126 1067
 	YY_BREAK
1127 1068
 case 27:
1128 1069
 YY_RULE_SETUP
1129
-#line 139 "tokenizer.lex"
1070
+#line 138 "tokenizer.lex"
1130 1071
 { return BAND; }
1131 1072
 	YY_BREAK
1132 1073
 case 28:
1133 1074
 YY_RULE_SETUP
1134
-#line 141 "tokenizer.lex"
1075
+#line 140 "tokenizer.lex"
1135 1076
 { return BOR; }
1136 1077
 	YY_BREAK
1137 1078
 case 29:
1138 1079
 YY_RULE_SETUP
1139
-#line 143 "tokenizer.lex"
1080
+#line 142 "tokenizer.lex"
1140 1081
 { return BXOR; }
1141 1082
 	YY_BREAK
1142 1083
 case 30:
1143 1084
 YY_RULE_SETUP
1144
-#line 145 "tokenizer.lex"
1085
+#line 144 "tokenizer.lex"
1145 1086
 { return BNOT; }
1146 1087
 	YY_BREAK
1147 1088
 case 31:
1148 1089
 YY_RULE_SETUP
1149
-#line 147 "tokenizer.lex"
1090
+#line 146 "tokenizer.lex"
1150 1091
 { return LAND; }
1151 1092
 	YY_BREAK
1152 1093
 case 32:
1153 1094
 YY_RULE_SETUP
1154
-#line 149 "tokenizer.lex"
1095
+#line 148 "tokenizer.lex"
1155 1096
 { return LAND; }
1156 1097
 	YY_BREAK
1157 1098
 case 33:
1158 1099
 YY_RULE_SETUP
1159
-#line 151 "tokenizer.lex"
1100
+#line 150 "tokenizer.lex"
1160 1101
 { return LOR; }
1161 1102
 	YY_BREAK
1162 1103
 case 34:
1163 1104
 YY_RULE_SETUP
1164
-#line 153 "tokenizer.lex"
1105
+#line 152 "tokenizer.lex"
1165 1106
 { return LOR; }
1166 1107
 	YY_BREAK
1167 1108
 case 35:
1168 1109
 YY_RULE_SETUP
1169
-#line 155 "tokenizer.lex"
1110
+#line 154 "tokenizer.lex"
1170 1111
 { return LNOT; }
1171 1112
 	YY_BREAK
1172 1113
 case 36:
1173 1114
 YY_RULE_SETUP
1174
-#line 157 "tokenizer.lex"
1115
+#line 156 "tokenizer.lex"
1175 1116
 { return LNOT; }
1176 1117
 	YY_BREAK
1177 1118
 case 37:
1178 1119
 YY_RULE_SETUP
1179
-#line 159 "tokenizer.lex"
1120
+#line 158 "tokenizer.lex"
1180 1121
 { *yylval = malloc(sizeof(long)); *((long *) *yylval) = 1; return INT;  }
1181 1122
 	YY_BREAK
1182 1123
 case 38:
1183 1124
 YY_RULE_SETUP
1184
-#line 161 "tokenizer.lex"
1125
+#line 160 "tokenizer.lex"
1185 1126
 { *yylval = malloc(sizeof(long)); *((long *) *yylval) = 1; return INT;  }
1186 1127
 	YY_BREAK
1187 1128
 case 39:
1188 1129
 YY_RULE_SETUP
1189
-#line 163 "tokenizer.lex"
1130
+#line 162 "tokenizer.lex"
1190 1131
 { *yylval = malloc(sizeof(long)); *((long *) *yylval) = 0; return INT;  }
1191 1132
 	YY_BREAK
1192 1133
 case 40:
1193 1134
 YY_RULE_SETUP
1194
-#line 165 "tokenizer.lex"
1135
+#line 164 "tokenizer.lex"
1195 1136
 { *yylval = malloc(sizeof(long)); *((long *) *yylval) = 0; return INT;  }
1196 1137
 	YY_BREAK
1197 1138
 case 41:
1198 1139
 YY_RULE_SETUP
1199
-#line 167 "tokenizer.lex"
1140
+#line 166 "tokenizer.lex"
1200 1141
 { return ASSIGN; }
1201 1142
 	YY_BREAK
1202 1143
 case 42:
1203 1144
 YY_RULE_SETUP
1204
-#line 169 "tokenizer.lex"
1145
+#line 168 "tokenizer.lex"
1205 1146
 { return ASSIGNPLUS; }
1206 1147
 	YY_BREAK
1207 1148
 case 43:
1208 1149
 YY_RULE_SETUP
1209
-#line 171 "tokenizer.lex"
1150
+#line 170 "tokenizer.lex"
1210 1151
 { return ASSIGNMINUS; }
1211 1152
 	YY_BREAK
1212 1153
 case 44:
1213 1154
 YY_RULE_SETUP
1214
-#line 173 "tokenizer.lex"
1155
+#line 172 "tokenizer.lex"
1215 1156
 { return ASSIGNSTAR; }
1216 1157
 	YY_BREAK
1217 1158
 case 45:
1218 1159
 YY_RULE_SETUP
1219
-#line 175 "tokenizer.lex"
1160
+#line 174 "tokenizer.lex"
1220 1161
 { return ASSIGNSLASH; }
1221 1162
 	YY_BREAK
1222 1163
 case 46:
1223 1164
 YY_RULE_SETUP
1224
-#line 177 "tokenizer.lex"
1165
+#line 176 "tokenizer.lex"
1225 1166
 { return ASSIGNDSTAR; }
1226 1167
 	YY_BREAK
1227 1168
 case 47:
1228 1169
 YY_RULE_SETUP
1229
-#line 179 "tokenizer.lex"
1170
+#line 178 "tokenizer.lex"
1230 1171
 { return ASSIGNBAND; }
1231 1172
 	YY_BREAK
1232 1173
 case 48:
1233 1174
 YY_RULE_SETUP
1234
-#line 181 "tokenizer.lex"
1175
+#line 180 "tokenizer.lex"
1235 1176
 { return ASSIGNBOR; }
1236 1177
 	YY_BREAK
1237 1178
 case 49:
1238 1179
 YY_RULE_SETUP
1239
-#line 183 "tokenizer.lex"
1180
+#line 182 "tokenizer.lex"
1240 1181
 { return ASSIGNBXOR; }
1241 1182
 	YY_BREAK
1242 1183
 case 50:
1243 1184
 YY_RULE_SETUP
1244
-#line 185 "tokenizer.lex"
1185
+#line 184 "tokenizer.lex"
1245 1186
 { return EQUAL; }
1246 1187
 	YY_BREAK
1247 1188
 case 51:
1248 1189
 YY_RULE_SETUP
1249
-#line 187 "tokenizer.lex"
1190
+#line 186 "tokenizer.lex"
1250 1191
 { return NEQUAL; }
1251 1192
 	YY_BREAK
1252 1193
 case 52:
1253 1194
 YY_RULE_SETUP
1254
-#line 189 "tokenizer.lex"
1195
+#line 188 "tokenizer.lex"
1255 1196
 { return LESS; }
1256 1197
 	YY_BREAK
1257 1198
 case 53:
1258 1199
 YY_RULE_SETUP
1259
-#line 191 "tokenizer.lex"
1200
+#line 190 "tokenizer.lex"
1260 1201
 { return GREATER; }
1261 1202
 	YY_BREAK
1262 1203
 case 54:
1263 1204
 YY_RULE_SETUP
1264
-#line 193 "tokenizer.lex"
1205
+#line 192 "tokenizer.lex"
1265 1206
 { return LESSEQ; }
1266 1207
 	YY_BREAK
1267 1208
 case 55:
1268 1209
 YY_RULE_SETUP
1269
-#line 195 "tokenizer.lex"
1210
+#line 194 "tokenizer.lex"
1270 1211
 { return GREATEREQ; }
1271 1212
 	YY_BREAK
1272 1213
 case 56:
1273 1214
 YY_RULE_SETUP
1274
-#line 197 "tokenizer.lex"
1215
+#line 196 "tokenizer.lex"
1275 1216
 { return RSHIFT; }
1276 1217
 	YY_BREAK
1277 1218
 case 57:
1278 1219
 YY_RULE_SETUP
1279
-#line 199 "tokenizer.lex"
1220
+#line 198 "tokenizer.lex"
1280 1221
 { return LSHIFT; }
1281 1222
 	YY_BREAK
1282 1223
 case 58:
1283 1224
 YY_RULE_SETUP
1284
-#line 201 "tokenizer.lex"
1225
+#line 200 "tokenizer.lex"
1285 1226
 { return LBRACE; }
1286 1227
 	YY_BREAK
1287 1228
 case 59:
1288 1229
 YY_RULE_SETUP
1289
-#line 203 "tokenizer.lex"
1230
+#line 202 "tokenizer.lex"
1290 1231
 { return RBRACE; }
1291 1232
 	YY_BREAK
1292 1233
 case 60:
1293 1234
 YY_RULE_SETUP
1294
-#line 205 "tokenizer.lex"
1235
+#line 204 "tokenizer.lex"
1295 1236
 { return LBRACKET; }
1296 1237
 	YY_BREAK
1297 1238
 case 61:
1298 1239
 YY_RULE_SETUP
1299
-#line 207 "tokenizer.lex"
1240
+#line 206 "tokenizer.lex"
1300 1241
 { return RBRACKET; }
1301 1242
 	YY_BREAK
1302 1243
 case 62:
1303 1244
 YY_RULE_SETUP
1304
-#line 209 "tokenizer.lex"
1245
+#line 208 "tokenizer.lex"
1305 1246
 { return BLPAREN; } /* "Breaking" paren, not allowed to introduce a call_expr */
1306 1247
 	YY_BREAK
1307 1248
 case 63:
1308 1249
 YY_RULE_SETUP
1309
-#line 211 "tokenizer.lex"
1250
+#line 210 "tokenizer.lex"
1310 1251
 { return LPAREN; } 
1311 1252
 	YY_BREAK
1312 1253
 case 64:
1313 1254
 YY_RULE_SETUP
1314
-#line 213 "tokenizer.lex"
1255
+#line 212 "tokenizer.lex"
1315 1256
 { return RPAREN; }
1316 1257
 	YY_BREAK
1317 1258
 case 65:
1318 1259
 YY_RULE_SETUP
1319
-#line 215 "tokenizer.lex"
1260
+#line 214 "tokenizer.lex"
1320 1261
 { return DOT; }
1321 1262
 	YY_BREAK
1322 1263
 case 66:
1323 1264
 YY_RULE_SETUP
1324
-#line 217 "tokenizer.lex"
1265
+#line 216 "tokenizer.lex"
1325 1266
 { return COLON; }
1326 1267
 	YY_BREAK
1327 1268
 case 67:
1328 1269
 YY_RULE_SETUP
1329
-#line 219 "tokenizer.lex"
1270
+#line 218 "tokenizer.lex"
1330 1271
 { return SEMICOLON; }
1331 1272
 	YY_BREAK
1332 1273
 case 68:
1333 1274
 YY_RULE_SETUP
1334
-#line 221 "tokenizer.lex"
1275
+#line 220 "tokenizer.lex"
1335 1276
 { return COMMA; }
1336 1277
 	YY_BREAK
1337 1278
 case 69:
1338 1279
 YY_RULE_SETUP
1339
-#line 223 "tokenizer.lex"
1280
+#line 222 "tokenizer.lex"
1340 1281
 { return POUND; }
1341 1282
 	YY_BREAK
1342 1283
 case 70:
1343 1284
 YY_RULE_SETUP
1344
-#line 225 "tokenizer.lex"
1285
+#line 224 "tokenizer.lex"
1345 1286
 { return TBANG; }
1346 1287
 	YY_BREAK
1347 1288
 case 71:
1348 1289
 YY_RULE_SETUP
1349
-#line 227 "tokenizer.lex"
1290
+#line 226 "tokenizer.lex"
1350 1291
 { *yylval = (void *) strdup(yytext); return IDENT; }
1351 1292
 	YY_BREAK
1352 1293
 case 72:
1353 1294
 /* rule 72 can match eol */
1354 1295
 YY_RULE_SETUP
1355
-#line 229 "tokenizer.lex"
1296
+#line 228 "tokenizer.lex"
1356 1297
 /* Skip comments */
1357 1298
 	YY_BREAK
1358 1299
 case 73:
1359 1300
 /* rule 73 can match eol */
1360 1301
 YY_RULE_SETUP
1361
-#line 231 "tokenizer.lex"
1302
+#line 230 "tokenizer.lex"
1362 1303
 /* Skip whitespace */
1363 1304
 	YY_BREAK
1364 1305
 case 74:
1365 1306
 YY_RULE_SETUP
1366
-#line 233 "tokenizer.lex"
1307
+#line 232 "tokenizer.lex"
1367 1308
 ECHO;
1368 1309
 	YY_BREAK
1369
-#line 1369 "lex.yy.c"
1310
+#line 1310 "lex.yy.c"
1370 1311
 case YY_STATE_EOF(INITIAL):
1371 1312
 	yyterminate();
1372 1313
 
@@ -1444,7 +1385,7 @@ case YY_STATE_EOF(INITIAL):
1444 1385
 				{
1445 1386
 				(yy_did_buffer_switch_on_eof) = 0;
1446 1387
 
1447
-				if ( yywrap( ) )
1388
+				if ( yywrap(  ) )
1448 1389
 					{
1449 1390
 					/* Note: because we've taken care in
1450 1391
 					 * yy_get_next_buffer() to have set up
@@ -1576,7 +1517,8 @@ static int yy_get_next_buffer (void)
1576 1517
 
1577 1518
 				b->yy_ch_buf = (char *)
1578 1519
 					/* Include room in for 2 EOB chars. */
1579
-					yyrealloc((void *) b->yy_ch_buf,(yy_size_t) (b->yy_buf_size + 2)  );
1520
+					yyrealloc( (void *) b->yy_ch_buf,
1521
+							 (yy_size_t) (b->yy_buf_size + 2)  );
1580 1522
 				}
1581 1523
 			else
1582 1524
 				/* Can't grow it, we don't own it. */
@@ -1608,7 +1550,7 @@ static int yy_get_next_buffer (void)
1608 1550
 		if ( number_to_move == YY_MORE_ADJ )
1609 1551
 			{
1610 1552
 			ret_val = EOB_ACT_END_OF_FILE;
1611
-			yyrestart(yyin  );
1553
+			yyrestart( yyin  );
1612 1554
 			}
1613 1555
 
1614 1556
 		else
@@ -1625,9 +1567,12 @@ static int yy_get_next_buffer (void)
1625 1567
 	if (((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
1626 1568
 		/* Extend the array by 50%, plus the number we really need. */
1627 1569
 		int new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
1628
-		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,(yy_size_t) new_size  );
1570
+		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc(
1571
+			(void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf, (yy_size_t) new_size  );
1629 1572
 		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
1630 1573
 			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
1574
+		/* "- 2" to take care of EOB's */
1575
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_size = (int) (new_size - 2);
1631 1576
 	}
1632 1577
 
1633 1578
 	(yy_n_chars) += number_to_move;
@@ -1779,13 +1724,13 @@ static int yy_get_next_buffer (void)
1779 1724
 					 */
1780 1725
 
1781 1726
 					/* Reset buffer status. */
1782
-					yyrestart(yyin );
1727
+					yyrestart( yyin );
1783 1728
 
1784 1729
 					/*FALLTHROUGH*/
1785 1730
 
1786 1731
 				case EOB_ACT_END_OF_FILE:
1787 1732
 					{
1788
-					if ( yywrap( ) )
1733
+					if ( yywrap(  ) )
1789 1734
 						return 0;
1790 1735
 
1791 1736
 					if ( ! (yy_did_buffer_switch_on_eof) )
@@ -1825,11 +1770,11 @@ static int yy_get_next_buffer (void)
1825 1770
 	if ( ! YY_CURRENT_BUFFER ){
1826 1771
         yyensure_buffer_stack ();
1827 1772
 		YY_CURRENT_BUFFER_LVALUE =
1828
-            yy_create_buffer(yyin,YY_BUF_SIZE );
1773
+            yy_create_buffer( yyin, YY_BUF_SIZE );
1829 1774
 	}
1830 1775
 
1831
-	yy_init_buffer(YY_CURRENT_BUFFER,input_file );
1832
-	yy_load_buffer_state( );
1776
+	yy_init_buffer( YY_CURRENT_BUFFER, input_file );
1777
+	yy_load_buffer_state(  );
1833 1778
 }
1834 1779
 
1835 1780
 /** Switch to a different input buffer.
@@ -1857,7 +1802,7 @@ static int yy_get_next_buffer (void)
1857 1802
 		}
1858 1803
 
1859 1804
 	YY_CURRENT_BUFFER_LVALUE = new_buffer;
1860
-	yy_load_buffer_state( );
1805
+	yy_load_buffer_state(  );
1861 1806
 
1862 1807
 	/* We don't actually know whether we did this switch during
1863 1808
 	 * EOF (yywrap()) processing, but the only time this flag
@@ -1885,7 +1830,7 @@ static void yy_load_buffer_state  (void)
1885 1830
 {
1886 1831
 	YY_BUFFER_STATE b;
1887 1832
     
1888
-	b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state )  );
1833
+	b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state )  );
1889 1834
 	if ( ! b )
1890 1835
 		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
1891 1836
 
@@ -1894,13 +1839,13 @@ static void yy_load_buffer_state  (void)
1894 1839
 	/* yy_ch_buf has to be 2 characters longer than the size given because
1895 1840
 	 * we need to put in 2 end-of-buffer characters.
1896 1841
 	 */
1897
-	b->yy_ch_buf = (char *) yyalloc((yy_size_t) (b->yy_buf_size + 2)  );
1842
+	b->yy_ch_buf = (char *) yyalloc( (yy_size_t) (b->yy_buf_size + 2)  );
1898 1843
 	if ( ! b->yy_ch_buf )
1899 1844
 		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
1900 1845
 
1901 1846
 	b->yy_is_our_buffer = 1;
1902 1847
 
1903
-	yy_init_buffer(b,file );
1848
+	yy_init_buffer( b, file );
1904 1849
 
1905 1850
 	return b;
1906 1851
 }
@@ -1919,9 +1864,9 @@ static void yy_load_buffer_state  (void)
1919 1864
 		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
1920 1865
 
1921 1866
 	if ( b->yy_is_our_buffer )
1922
-		yyfree((void *) b->yy_ch_buf  );
1867
+		yyfree( (void *) b->yy_ch_buf  );
1923 1868
 
1924
-	yyfree((void *) b  );
1869
+	yyfree( (void *) b  );
1925 1870
 }
1926 1871
 
1927 1872
 /* Initializes or reinitializes a buffer.
@@ -1933,7 +1878,7 @@ static void yy_load_buffer_state  (void)
1933 1878
 {
1934 1879
 	int oerrno = errno;
1935 1880
     
1936
-	yy_flush_buffer(b );
1881
+	yy_flush_buffer( b );
1937 1882
 
1938 1883
 	b->yy_input_file = file;
1939 1884
 	b->yy_fill_buffer = 1;
@@ -1976,7 +1921,7 @@ static void yy_load_buffer_state  (void)
1976 1921
 	b->yy_buffer_status = YY_BUFFER_NEW;
1977 1922
 
1978 1923
 	if ( b == YY_CURRENT_BUFFER )
1979
-		yy_load_buffer_state( );
1924
+		yy_load_buffer_state(  );
1980 1925
 }
1981 1926
 
1982 1927
 /** Pushes the new state onto the stack. The new state becomes
@@ -2007,7 +1952,7 @@ void yypush_buffer_state (YY_BUFFER_STATE new_buffer )
2007 1952
 	YY_CURRENT_BUFFER_LVALUE = new_buffer;
2008 1953
 
2009 1954
 	/* copied from yy_switch_to_buffer. */
2010
-	yy_load_buffer_state( );
1955
+	yy_load_buffer_state(  );
2011 1956
 	(yy_did_buffer_switch_on_eof) = 1;
2012 1957
 }
2013 1958
 
@@ -2026,7 +1971,7 @@ void yypop_buffer_state (void)
2026 1971
 		--(yy_buffer_stack_top);
2027 1972
 
2028 1973
 	if (YY_CURRENT_BUFFER) {
2029
-		yy_load_buffer_state( );
1974
+		yy_load_buffer_state(  );
2030 1975
 		(yy_did_buffer_switch_on_eof) = 1;
2031 1976
 	}
2032 1977
 }
@@ -2093,7 +2038,7 @@ YY_BUFFER_STATE yy_scan_buffer  (char * base, yy_size_t  size )
2093 2038
 		/* They forgot to leave room for the EOB's. */
2094 2039
 		return NULL;
2095 2040
 
2096
-	b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state )  );
2041
+	b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state )  );
2097 2042
 	if ( ! b )
2098 2043
 		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
2099 2044
 
@@ -2107,7 +2052,7 @@ YY_BUFFER_STATE yy_scan_buffer  (char * base, yy_size_t  size )
2107 2052
 	b->yy_fill_buffer = 0;
2108 2053
 	b->yy_buffer_status = YY_BUFFER_NEW;
2109 2054
 
2110
-	yy_switch_to_buffer(b  );
2055
+	yy_switch_to_buffer( b  );
2111 2056
 
2112 2057
 	return b;
2113 2058
 }
@@ -2123,7 +2068,7 @@ YY_BUFFER_STATE yy_scan_buffer  (char * base, yy_size_t  size )
2123 2068
 YY_BUFFER_STATE yy_scan_string (const char * yystr )
2124 2069
 {
2125 2070
     
2126
-	return yy_scan_bytes(yystr,(int) strlen(yystr) );
2071
+	return yy_scan_bytes( yystr, (int) strlen(yystr) );
2127 2072
 }
2128 2073
 
2129 2074
 /** Setup the input buffer state to scan the given bytes. The next call to yylex() will
@@ -2142,7 +2087,7 @@ YY_BUFFER_STATE yy_scan_bytes  (const char * yybytes, int  _yybytes_len )
2142 2087
     
2143 2088
 	/* Get memory for full buffer, including space for trailing EOB's. */
2144 2089
 	n = (yy_size_t) (_yybytes_len + 2);
2145
-	buf = (char *) yyalloc(n  );
2090
+	buf = (char *) yyalloc( n  );
2146 2091
 	if ( ! buf )
2147 2092
 		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
2148 2093
 
@@ -2151,7 +2096,7 @@ YY_BUFFER_STATE yy_scan_bytes  (const char * yybytes, int  _yybytes_len )
2151 2096
 
2152 2097
 	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
2153 2098
 
2154
-	b = yy_scan_buffer(buf,n );
2099
+	b = yy_scan_buffer( buf, n );
2155 2100
 	if ( ! b )
2156 2101
 		YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
2157 2102
 
@@ -2169,7 +2114,7 @@ YY_BUFFER_STATE yy_scan_bytes  (const char * yybytes, int  _yybytes_len )
2169 2114
 
2170 2115
 static void yynoreturn yy_fatal_error (const char* msg )
2171 2116
 {
2172
-			(void) fprintf( stderr, "%s\n", msg );
2117
+			fprintf( stderr, "%s\n", msg );
2173 2118
 	exit( YY_EXIT_FAILURE );
2174 2119
 }
2175 2120
 
@@ -2304,7 +2249,7 @@ int yylex_destroy  (void)
2304 2249
     
2305 2250
     /* Pop the buffer stack, destroying each element. */
2306 2251
 	while(YY_CURRENT_BUFFER){
2307
-		yy_delete_buffer(YY_CURRENT_BUFFER  );
2252
+		yy_delete_buffer( YY_CURRENT_BUFFER  );
2308 2253
 		YY_CURRENT_BUFFER_LVALUE = NULL;
2309 2254
 		yypop_buffer_state();
2310 2255
 	}
@@ -2370,7 +2315,7 @@ void yyfree (void * ptr )
2370 2315
 
2371 2316
 #define YYTABLES_NAME "yytables"
2372 2317
 
2373
-#line 233 "tokenizer.lex"
2318
+#line 232 "tokenizer.lex"
2374 2319
 
2375 2320
 
2376 2321
 int yywrap(void) {

+ 60
- 2
object.c View File

@@ -31,6 +31,18 @@ sol_object_t *sol_cast_float(sol_state_t *state, sol_object_t *obj) {
31 31
 	return res;
32 32
 }
33 33
 
34
+sol_object_t *sol_cast_buffer(sol_state_t *state, sol_object_t *obj) {
35
+	sol_object_t *res, *ls;
36
+	if(sol_is_buffer(obj)) {
37
+		return sol_incref(obj);
38
+	}
39
+	ls = sol_new_list(state);
40
+	sol_list_insert(state, ls, 0, obj);
41
+	res = CALL_METHOD(state, obj, tobuffer, ls);
42
+	sol_obj_free(ls);
43
+	return res;
44
+}
45
+
34 46
 sol_object_t *sol_cast_string(sol_state_t *state, sol_object_t *obj) {
35 47
 	sol_object_t *res, *ls;
36 48
 	if(sol_is_string(obj)) {
@@ -375,7 +387,7 @@ sol_object_t *sol_map_get(sol_state_t *state, sol_object_t *map, sol_object_t *k
375 387
 }
376 388
 
377 389
 sol_object_t *sol_map_get_name(sol_state_t *state, sol_object_t *map, char *name) {
378
-	sol_object_t *key = sol_new_string(state, name);
390
+	sol_object_t *key = sol_new_buffer(state, name, strlen(name), OWN_NONE, NULL, NULL);
379 391
 	sol_object_t *res = sol_map_get(state, map, key);
380 392
 	sol_obj_free(key);
381 393
 	return res;
@@ -414,7 +426,7 @@ void sol_map_set(sol_state_t *state, sol_object_t *map, sol_object_t *key, sol_o
414 426
 }
415 427
 
416 428
 void sol_map_set_name(sol_state_t *state, sol_object_t *map, char *name, sol_object_t *val) {
417
-	sol_object_t *key = sol_new_string(state, name);
429
+	sol_object_t *key = sol_new_buffer(state, name, strlen(name), OWN_NONE, NULL, NULL);
418 430
 	sol_map_set(state, map, key, val);
419 431
 	sol_obj_free(key);
420 432
 }
@@ -554,6 +566,52 @@ sol_object_t *sol_new_buffer(sol_state_t *state, void *buffer, ssize_t sz, sol_o
554 566
 	return res;
555 567
 }
556 568
 
569
+int sol_buffer_cmp(sol_state_t *state, sol_object_t *buf, const char *s) {
570
+	size_t len = strlen(s);
571
+	if(buf->sz != -1 && buf->sz < len) len = buf->sz;
572
+	return memcmp(buf->buffer, s, len);
573
+}
574
+
575
+sol_object_t *sol_buffer_concat(sol_state_t *state, sol_object_t *a, sol_object_t *b) {
576
+	sol_object_t *ba = sol_cast_buffer(state, a), *bb = sol_cast_buffer(state, b);
577
+	char *buf;
578
+	size_t total;
579
+	if(ba->sz < 0 || bb->sz < 0) {
580
+		sol_obj_free(ba);
581
+		sol_obj_free(bb);
582
+		return sol_set_error_string(state, "Concatenate unsized buffer");
583
+	}
584
+	total = ba->sz + bb->sz;
585
+	buf = malloc(sizeof(char) * total);
586
+	if(!buf) {
587
+		sol_obj_free(ba);
588
+		sol_obj_free(bb);
589
+		return sol_incref(state->OutOfMemory);
590
+	}
591
+	memcpy(buf, ba->buffer, ba->sz);
592
+	memcpy(buf + ba->sz, bb->buffer, bb->sz);
593
+	sol_obj_free(ba);
594
+	sol_obj_free(bb);
595
+	return sol_new_buffer(state, buf, total, OWN_FREE, NULL, NULL);
596
+}
597
+
598
+sol_object_t *sol_buffer_concat_cstr(sol_state_t *state, sol_object_t *a, char *b) {
599
+	sol_object_t *buf = sol_new_buffer(state, b, strlen(b), OWN_NONE, NULL, NULL);
600
+	sol_object_t *res = sol_buffer_concat(state, a, buf);
601
+	sol_obj_free(buf);
602
+	return res;
603
+}
604
+
605
+char *sol_buffer_strdup(sol_object_t *a) {
606
+	char *b;
607
+	if(a->sz < 0) return NULL;
608
+	b = malloc(a->sz + 1);
609
+	if(!b) return NULL;
610
+	strncpy(b, a->buffer, a->sz);
611
+	b[a->sz] = '\0';
612
+	return b;
613
+}
614
+
557 615
 sol_object_t *sol_f_buffer_free(sol_state_t *state, sol_object_t *buf) {
558 616
 	switch(buf->own) {
559 617
 		case OWN_FREE:

+ 58
- 44
parser.tab.c View File

@@ -526,8 +526,8 @@ static const yytype_uint16 yyrline[] =
526 526
      361,   365,   366,   370,   371,   379,   383,   392,   401,   413,
527 527
      417,   418,   429,   433,   434,   448,   449,   453,   454,   455,
528 528
      456,   457,   458,   462,   463,   464,   468,   472,   473,   478,
529
-     479,   510,   511,   546,   559,   594,   598,   599,   604,   605,
530
-     617,   622,   634,   635,   639,   640
529
+     479,   524,   525,   560,   573,   608,   612,   613,   618,   619,
530
+     638,   643,   655,   656,   660,   661
531 531
 };
532 532
 #endif
533 533
 
@@ -2453,7 +2453,7 @@ yyreduce:
2453 2453
 
2454 2454
   case 90:
2455 2455
 #line 456 "parser.y" /* yacc.c:1646  */
2456
-    { (yyval) = NEW_EX(); AS_EX((yyval))->type = EX_LIT; AS_EX((yyval))->lit = NEW(lit_node); AS_EX((yyval))->lit->type = LIT_STRING; AS_EX((yyval))->lit->str = (yyvsp[0]); }
2456
+    { (yyval) = NEW_EX(); AS_EX((yyval))->type = EX_LIT; AS_EX((yyval))->lit = NEW(lit_node); AS_EX((yyval))->lit->type = LIT_BUFFER; AS_EX((yyval))->lit->buf = (yyvsp[0]); }
2457 2457
 #line 2458 "parser.tab.c" /* yacc.c:1646  */
2458 2458
     break;
2459 2459
 
@@ -2519,24 +2519,31 @@ yyreduce:
2519 2519
 #line 479 "parser.y" /* yacc.c:1646  */
2520 2520
     {
2521 2521
 	exprlist_node *cur = (yyvsp[-1]);
2522
-	while(cur->next) cur = cur->next;
2523
-	cur->next = NEW(exprlist_node);
2524
-	cur = cur->next;
2525
-	cur->expr = (yyvsp[0]);
2526
-	cur->next = NULL;
2527
-	(yyval) = (yyvsp[-1]);
2522
+	if(!cur) {
2523
+		cur = NEW(exprlist_node);
2524
+		cur->expr = (yyvsp[0]);
2525
+		cur->next = NULL;
2526
+		(yyval) = cur;
2527
+	} else {
2528
+		while(cur->next) cur = cur->next;
2529
+		cur->next = NEW(exprlist_node);
2530
+		cur = cur->next;
2531
+		cur->expr = (yyvsp[0]);
2532
+		cur->next = NULL;
2533
+		(yyval) = (yyvsp[-1]);
2534
+	}
2528 2535
 }
2529
-#line 2530 "parser.tab.c" /* yacc.c:1646  */
2536
+#line 2537 "parser.tab.c" /* yacc.c:1646  */
2530 2537
     break;
2531 2538
 
2532 2539
   case 101:
2533
-#line 510 "parser.y" /* yacc.c:1646  */
2540
+#line 524 "parser.y" /* yacc.c:1646  */
2534 2541
     { (yyval) = NULL; }
2535
-#line 2536 "parser.tab.c" /* yacc.c:1646  */
2542
+#line 2543 "parser.tab.c" /* yacc.c:1646  */
2536 2543
     break;
2537 2544
 
2538 2545
   case 102:
2539
-#line 511 "parser.y" /* yacc.c:1646  */
2546
+#line 525 "parser.y" /* yacc.c:1646  */
2540 2547
     {
2541 2548
 	paramlist_node *pl = (yyvsp[-3]);
2542 2549
 	identlist_node *curk;
@@ -2572,11 +2579,11 @@ yyreduce:
2572 2579
 	curv->next = NULL;
2573 2580
 	(yyval) = pl;
2574 2581
 }
2575
-#line 2576 "parser.tab.c" /* yacc.c:1646  */
2582
+#line 2583 "parser.tab.c" /* yacc.c:1646  */
2576 2583
     break;
2577 2584
 
2578 2585
   case 103:
2579
-#line 546 "parser.y" /* yacc.c:1646  */
2586
+#line 560 "parser.y" /* yacc.c:1646  */
2580 2587
     {
2581 2588
 	paramlist_node *pl = (yyvsp[-2]);
2582 2589
 	if(!pl) {
@@ -2590,11 +2597,11 @@ yyreduce:
2590 2597
 	pl-> rest = (yyvsp[0]);
2591 2598
 	(yyval) = pl;
2592 2599
 }
2593
-#line 2594 "parser.tab.c" /* yacc.c:1646  */
2600
+#line 2601 "parser.tab.c" /* yacc.c:1646  */
2594 2601
     break;
2595 2602
 
2596 2603
   case 104:
2597
-#line 559 "parser.y" /* yacc.c:1646  */
2604
+#line 573 "parser.y" /* yacc.c:1646  */
2598 2605
     {
2599 2606
 	paramlist_node *pl = (yyvsp[-2]);
2600 2607
 	identlist_node *cura;
@@ -2630,63 +2637,70 @@ yyreduce:
2630 2637
 	curn->next = NULL;
2631 2638
 	(yyval) = pl;
2632 2639
 }
2633
-#line 2634 "parser.tab.c" /* yacc.c:1646  */
2640
+#line 2641 "parser.tab.c" /* yacc.c:1646  */
2634 2641
     break;
2635 2642
 
2636 2643
   case 105:
2637
-#line 594 "parser.y" /* yacc.c:1646  */
2644
+#line 608 "parser.y" /* yacc.c:1646  */
2638 2645
     { (yyval) = (yyvsp[-1]); }
2639
-#line 2640 "parser.tab.c" /* yacc.c:1646  */
2646
+#line 2647 "parser.tab.c" /* yacc.c:1646  */
2640 2647
     break;
2641 2648
 
2642 2649
   case 106:
2643
-#line 598 "parser.y" /* yacc.c:1646  */
2650
+#line 612 "parser.y" /* yacc.c:1646  */
2644 2651
     { (yyval) = NULL; }
2645
-#line 2646 "parser.tab.c" /* yacc.c:1646  */
2652
+#line 2653 "parser.tab.c" /* yacc.c:1646  */
2646 2653
     break;
2647 2654
 
2648 2655
   case 107:
2649
-#line 599 "parser.y" /* yacc.c:1646  */
2656
+#line 613 "parser.y" /* yacc.c:1646  */
2650 2657
     {
2651 2658
 	(yyval) = NEW(assoclist_node);
2652 2659
 	AS((yyval), assoclist_node)->item = (yyvsp[0]);
2653 2660
 	AS((yyval), assoclist_node)->next = NULL;
2654 2661
 }
2655
-#line 2656 "parser.tab.c" /* yacc.c:1646  */
2662
+#line 2663 "parser.tab.c" /* yacc.c:1646  */
2656 2663
     break;
2657 2664
 
2658 2665
   case 108:
2659
-#line 604 "parser.y" /* yacc.c:1646  */
2666
+#line 618 "parser.y" /* yacc.c:1646  */
2660 2667
     { (yyval) = (yyvsp[-1]); }
2661
-#line 2662 "parser.tab.c" /* yacc.c:1646  */
2668
+#line 2669 "parser.tab.c" /* yacc.c:1646  */
2662 2669
     break;
2663 2670
 
2664 2671
   case 109:
2665
-#line 605 "parser.y" /* yacc.c:1646  */
2672
+#line 619 "parser.y" /* yacc.c:1646  */
2666 2673
     {
2667 2674
 	assoclist_node *cur = (yyvsp[-1]);
2668
-	while(cur->next) cur = cur->next;
2669
-	cur->next = NEW(assoclist_node);
2670
-	cur = cur->next;
2671
-	cur->item = (yyvsp[0]);
2672
-	cur->next = NULL;
2673
-	(yyval) = (yyvsp[-1]);
2675
+	if(!cur) {
2676
+		cur = NEW(assoclist_node);
2677
+		cur->item = (yyvsp[0]);
2678
+		cur->next = NULL;
2679
+		(yyval) = cur;
2680
+	} else {
2681
+		while(cur->next) cur = cur->next;
2682
+		cur->next = NEW(assoclist_node);
2683
+		cur = cur->next;
2684
+		cur->item = (yyvsp[0]);
2685
+		cur->next = NULL;
2686
+		(yyval) = (yyvsp[-1]);
2687
+	}
2674 2688
 }
2675
-#line 2676 "parser.tab.c" /* yacc.c:1646  */
2689
+#line 2690 "parser.tab.c" /* yacc.c:1646  */
2676 2690
     break;
2677 2691
 
2678 2692
   case 110:
2679
-#line 617 "parser.y" /* yacc.c:1646  */
2693
+#line 638 "parser.y" /* yacc.c:1646  */
2680 2694
     {
2681 2695
 	(yyval) = NEW(associtem_node);
2682 2696
 	AS((yyval), associtem_node)->key = (yyvsp[-3]);
2683 2697
 	AS((yyval), associtem_node)->value = (yyvsp[0]);
2684 2698
 }
2685
-#line 2686 "parser.tab.c" /* yacc.c:1646  */
2699
+#line 2700 "parser.tab.c" /* yacc.c:1646  */
2686 2700
     break;
2687 2701
 
2688 2702
   case 111:
2689
-#line 622 "parser.y" /* yacc.c:1646  */
2703
+#line 643 "parser.y" /* yacc.c:1646  */
2690 2704
     {
2691 2705
 	(yyval) = NEW(associtem_node);
2692 2706
 	AS((yyval), associtem_node)->key = NEW_EX();
@@ -2696,23 +2710,23 @@ yyreduce:
2696 2710
 	AS((yyval), associtem_node)->key->lit->str = (yyvsp[-2]);
2697 2711
 	AS((yyval), associtem_node)->value = (yyvsp[0]);
2698 2712
 }
2699
-#line 2700 "parser.tab.c" /* yacc.c:1646  */
2713
+#line 2714 "parser.tab.c" /* yacc.c:1646  */
2700 2714
     break;
2701 2715
 
2702 2716
   case 114:
2703
-#line 639 "parser.y" /* yacc.c:1646  */
2717
+#line 660 "parser.y" /* yacc.c:1646  */
2704 2718
     { (yyval) = (yyvsp[0]); }
2705
-#line 2706 "parser.tab.c" /* yacc.c:1646  */
2719
+#line 2720 "parser.tab.c" /* yacc.c:1646  */
2706 2720
     break;
2707 2721
 
2708 2722
   case 115:
2709
-#line 640 "parser.y" /* yacc.c:1646  */
2723
+#line 661 "parser.y" /* yacc.c:1646  */
2710 2724
     { (yyval) = NULL; }
2711
-#line 2712 "parser.tab.c" /* yacc.c:1646  */
2725
+#line 2726 "parser.tab.c" /* yacc.c:1646  */
2712 2726
     break;
2713 2727
 
2714 2728
 
2715
-#line 2716 "parser.tab.c" /* yacc.c:1646  */
2729
+#line 2730 "parser.tab.c" /* yacc.c:1646  */
2716 2730
       default: break;
2717 2731
     }
2718 2732
   /* User semantic actions sometimes alter yychar, and that requires
@@ -2947,7 +2961,7 @@ yyreturn:
2947 2961
 #endif
2948 2962
   return yyresult;
2949 2963
 }
2950
-#line 643 "parser.y" /* yacc.c:1906  */
2964
+#line 664 "parser.y" /* yacc.c:1906  */
2951 2965
 
2952 2966
 
2953 2967
 // TODO

+ 40
- 19
parser.y View File

@@ -453,7 +453,7 @@ lit_expr:
453 453
   INT { $$ = NEW_EX(); AS_EX($$)->type = EX_LIT; AS_EX($$)->lit = NEW(lit_node); AS_EX($$)->lit->type = LIT_INT; AS_EX($$)->lit->ival = *AS($1, long); free($1); }
454 454
 | MINUS INT { $$ = NEW_EX(); AS_EX($$)->type = EX_LIT; AS_EX($$)->lit = NEW(lit_node); AS_EX($$)->lit->type = LIT_INT; AS_EX($$)->lit->ival = -(*AS($2, long)); free($2); }
455 455
 | FLOAT { $$ = NEW_EX(); AS_EX($$)->type = EX_LIT; AS_EX($$)->lit = NEW(lit_node); AS_EX($$)->lit->type = LIT_FLOAT; AS_EX($$)->lit->fval = *AS($1, double); free($1); }
456
-| STRING { $$ = NEW_EX(); AS_EX($$)->type = EX_LIT; AS_EX($$)->lit = NEW(lit_node); AS_EX($$)->lit->type = LIT_STRING; AS_EX($$)->lit->str = $1; }
456
+| STRING { $$ = NEW_EX(); AS_EX($$)->type = EX_LIT; AS_EX($$)->lit = NEW(lit_node); AS_EX($$)->lit->type = LIT_BUFFER; AS_EX($$)->lit->buf = $1; }
457 457
 | NONE { $$ = NEW_EX(); AS_EX($$)->type = EX_LIT; AS_EX($$)->lit = NEW(lit_node); AS_EX($$)->lit->type = LIT_NONE; }
458 458
 | gen_expr { $$ = $1; }
459 459
 ;
@@ -478,12 +478,19 @@ expr_list:
478 478
 | expr_list COMMA { $$ = $1; }
479 479
 | expr_list expr {
480 480
 	exprlist_node *cur = $1;
481
-	while(cur->next) cur = cur->next;
482
-	cur->next = NEW(exprlist_node);
483
-	cur = cur->next;
484
-	cur->expr = $2;
485
-	cur->next = NULL;
486
-	$$ = $1;
481
+	if(!cur) {
482
+		cur = NEW(exprlist_node);
483
+		cur->expr = $2;
484
+		cur->next = NULL;
485
+		$$ = cur;
486
+	} else {
487
+		while(cur->next) cur = cur->next;
488
+		cur->next = NEW(exprlist_node);
489
+		cur = cur->next;
490
+		cur->expr = $2;
491
+		cur->next = NULL;
492
+		$$ = $1;
493
+	}
487 494
 }
488 495
 ;
489 496
 
@@ -497,12 +504,19 @@ ident_list:
497 504
 | ident_list COMMA { $$ = $1; }
498 505
 | ident_list IDENT {
499 506
 	identlist_node *cur = $1;
500
-	while(cur->next) cur = cur->next;
501
-	cur->next = NEW(identlist_node);
502
-	cur = cur->next;
503
-	cur->ident = $2;
504
-	cur->next = NULL;
505
-	$$ = $1;
507
+	if(!cur) {
508
+		cur = NEW(identlist_node);
509
+		cur->ident = $2;
510
+		cur->next = NULL;
511
+		$$ = cur;
512
+	} else {
513
+		while(cur->next) cur = cur->next;
514
+		cur->next = NEW(identlist_node);
515
+		cur = cur->next;
516
+		cur->ident = $2;
517
+		cur->next = NULL;
518
+		$$ = $1;
519
+	}
506 520
 }
507 521
 ;
508 522
 
@@ -604,12 +618,19 @@ assoc_list:
604 618
 | assoc_list COMMA { $$ = $1; }
605 619
 | assoc_list assoc_item {
606 620
 	assoclist_node *cur = $1;
607
-	while(cur->next) cur = cur->next;
608
-	cur->next = NEW(assoclist_node);
609
-	cur = cur->next;
610
-	cur->item = $2;
611
-	cur->next = NULL;
612
-	$$ = $1;
621
+	if(!cur) {
622
+		cur = NEW(assoclist_node);
623
+		cur->item = $2;
624
+		cur->next = NULL;
625
+		$$ = cur;
626
+	} else {
627
+		while(cur->next) cur = cur->next;
628
+		cur->next = NEW(assoclist_node);
629
+		cur = cur->next;
630
+		cur->item = $2;
631
+		cur->next = NULL;
632
+		$$ = $1;
633
+	}
613 634
 }
614 635
 ;
615 636
 

+ 3
- 3
programs/test.sol View File

@@ -331,9 +331,9 @@ print('(buffer.sizeof.ptr = ', buffer.sizeof.ptr, ')')
331 331
 print('(buffer.sizeof.int = ', buffer.sizeof.int, ')')
332 332
 print('(buffer.sizeof.int*2 = ', buffer.sizeof.int*2, ')')
333 333
 print('(buffer.sizeof.int*2 + buffer.sizeof.ptr = ', buffer.sizeof.int*2 + (buffer.sizeof.ptr), ')')
334
-bs = b:get(buffer.type.ptr, buffer.sizeof.int*2 + (buffer.sizeof.ptr))
335
-print('...string buffer:', bs)
336
-print('...with value:', bs:get(buffer.type.cstr))
334
+--bs = b:get(buffer.type.ptr, buffer.sizeof.int*2 + (buffer.sizeof.ptr))
335
+--print('...string buffer:', bs)
336
+--print('...with value:', bs:get(buffer.type.cstr))
337 337
 
338 338
 print('--- IO redirection')
339 339
 

+ 15
- 0
runtime.c View File

@@ -108,6 +108,12 @@ expr_node *ex_copy(expr_node *old) {
108 108
 					new->lit->str = strdup(old->lit->str);
109 109
 					break;
110 110
 
111
+				case LIT_BUFFER:
112
+					new->lit->buf = malloc(sizeof(unsigned long) + LENGTH_OF(old->lit->buf) * sizeof(char));
113
+					LENGTH_OF(new->lit->buf) = LENGTH_OF(old->lit->buf);
114
+					memcpy(BYTES_OF(new->lit->buf), BYTES_OF(old->lit->buf), LENGTH_OF(old->lit->buf) * sizeof(char));
115
+					break;
116
+
111 117
 				case LIT_NONE:
112 118
 					break;
113 119
 
@@ -358,6 +364,9 @@ void ex_free(expr_node *expr) {
358 364
 			if(expr->lit->type == LIT_STRING) {
359 365
 				free(expr->lit->str);
360 366
 			}
367
+			if(expr->lit->type == LIT_BUFFER) {
368
+				free(expr->lit->buf);
369
+			}
361 370
 			free(expr->lit);
362 371
 			break;
363 372
 
@@ -497,6 +506,7 @@ sol_object_t *sol_eval_inner(sol_state_t *state, expr_node *expr, jmp_buf jmp) {
497 506
 	exprlist_node *cure = NULL;
498 507
 	assoclist_node *cura = NULL;
499 508
 	identlist_node *curi = NULL;
509
+	char *buf;
500 510
 	if(!expr) {
501 511
 		return sol_set_error_string(state, "Evaluate NULL expression");
502 512
 	}
@@ -516,6 +526,11 @@ sol_object_t *sol_eval_inner(sol_state_t *state, expr_node *expr, jmp_buf jmp) {
516 526
 					return sol_new_string(state, expr->lit->str);
517 527
 					break;
518 528
 
529
+				case LIT_BUFFER:
530
+					buf = malloc(LENGTH_OF(expr->lit->buf));
531
+					memcpy(buf, BYTES_OF(expr->lit->buf), LENGTH_OF(expr->lit->buf));
532
+					return sol_new_buffer(state, buf, LENGTH_OF(expr->lit->buf), OWN_FREE, NULL, NULL);
533
+
519 534
 				case LIT_NONE:
520 535
 					return sol_incref(state->None);
521 536
 					break;

+ 29
- 0
ser.c View File

@@ -29,10 +29,12 @@ char *sol_BytecodeNames[] = {
29 29
 	"BC_LIT_INT",
30 30
 	"BC_LIT_FLOAT",
31 31
 	"BC_LIT_STRING",
32
+	"BC_LIT_BUFFER",
32 33
 	"BC_LIT_NONE",
33 34
 	"BC_INT",
34 35
 	"BC_FLOAT",
35 36
 	"BC_STRING",
37
+	"BC_BUFFER",
36 38
 	"BC_LIST_ST",
37 39
 	"BC_LIST_EX",
38 40
 	"BC_LIST_AS",
@@ -251,6 +253,11 @@ void sol_ser_lit(FILE *io, lit_node *lit) {
251 253
 			sol_ser_str(io, lit->str);
252 254
 			break;
253 255
 
256
+		case LIT_BUFFER:
257
+			fputc(BC_LIT_BUFFER, io);
258
+			sol_ser_buf(io, lit->buf);
259
+			break;
260
+
254 261
 		case LIT_NONE:
255 262
 			fputc(BC_LIT_NONE, io);
256 263
 			break;
@@ -273,6 +280,12 @@ void sol_ser_str(FILE *io, const char *s) {
273 280
 	fwrite(s, sizeof(char), len, io);
274 281
 }
275 282
 
283
+void sol_ser_buf(FILE *io, unsigned long *buf) {
284
+	fputc(BC_BUFFER, io);
285
+	fwrite(buf, sizeof(unsigned long), 1, io);
286
+	fwrite(BYTES_OF(buf), sizeof(char), LENGTH_OF(buf), io);
287
+}
288
+
276 289
 void sol_ser_int(FILE *io, long i) {
277 290
 	fputc(BC_INT, io);
278 291
 	fwrite(&i, sizeof(long), 1, io);
@@ -350,6 +363,7 @@ void *sol_deser_lit(FILE *io) {
350 363
 		case BC_LIT_INT:
351 364
 		case BC_LIT_FLOAT:
352 365
 		case BC_LIT_STRING:
366
+		case BC_LIT_BUFFER:
353 367
 		case BC_LIT_NONE:
354 368
 			;
355 369
 	}
@@ -540,6 +554,12 @@ void *sol_deser(FILE *io) {
540 554
 			AS(obj, lit_node)->str = sol_deser_checked(io, BC_STRING);
541 555
 			return obj;
542 556
 
557
+		case BC_LIT_BUFFER:
558
+			obj = NEW(lit_node);
559
+			AS(obj, lit_node)->type = LIT_BUFFER;
560
+			AS(obj, lit_node)->buf = sol_deser_checked(io, BC_BUFFER);
561
+			return obj;
562
+
543 563
 		case BC_LIT_NONE:
544 564
 			obj = NEW(lit_node);
545 565
 			AS(obj, lit_node)->type = LIT_NONE;
@@ -564,6 +584,15 @@ void *sol_deser(FILE *io) {
564 584
 			free(node);
565 585
 			return obj;
566 586
 
587
+		case BC_BUFFER:
588
+			node = NEW(unsigned long);
589
+			fread(node, sizeof(unsigned long), 1, io);
590
+			obj = malloc(sizeof(unsigned long) + sizeof(char) * (*AS(node, unsigned long)));
591
+			LENGTH_OF(obj) = *AS(node, unsigned long);
592
+			fread(BYTES_OF(obj), sizeof(char), LENGTH_OF(obj), io);
593
+			free(node);
594
+			return obj;
595
+
567 596
 		case BC_LIST_ST:
568 597
 			while((b = fgetc(io)) != BC_ENDLIST) {
569 598
 				ungetc(b, io);

+ 37
- 3
sol.h View File

@@ -10,7 +10,7 @@
10 10
 #include "dsl/dsl.h"
11 11
 
12 12
 /** The version of the project, as made available through `debug.version`. */
13
-#define SOL_VERSION "0.3a4"
13
+#define SOL_VERSION "0.4a0"
14 14
 /** The hexadecimal version of the project, formatted 0xAAIIRPP where:
15 15
  * 
16 16
  * - AA is the two-digit major version
@@ -23,7 +23,7 @@
23 23
  * version shall be available in all versions numerically greater than it
24 24
  * (unless they are later deprecated or removed).
25 25
  */
26
-#define SOL_HEXVER 0x0003A04
26
+#define SOL_HEXVER 0x0004A00
27 27
 
28 28
 #ifndef SOL_BUILD_HOST
29 29
 #define SOL_BUILD_HOST "(unknown host)"
@@ -160,6 +160,8 @@ typedef struct {
160 160
 	sol_cfunc_t tofloat;
161 161
 	/** Called with [this] to cast "this" to a string object. This generally shouldn't raise an error, and usually falls back to a simple representation. */
162 162
 	sol_cfunc_t tostring;
163
+	/** Called with [this] to cast "this" to a buffer object. This generally shouldn't raise an error, and usually falls back to converting the tostring to a buffer (which might be lossy if the string has embedded NULs). */
164
+	sol_cfunc_t tobuffer;
163 165
 	/** Called with [this] to provide a representation of "this", in the sense that it is human-readable and informative. This usually falls back to tostring. */
164 166
 	sol_cfunc_t repr;
165 167
 	/** Called with this (*not a list*) as a result of calling `sol_init_object`. Since this is usually called from a constructor anyway, it's usually fairly useless. It should return this. */
@@ -704,6 +706,11 @@ sol_object_t *sol_f_default_tostring(sol_state_t *, sol_object_t *);
704 706
  * Returns tostring(object).
705 707
  */
706 708
 sol_object_t *sol_f_default_repr(sol_state_t *, sol_object_t *);
709
+/** Default tobuffer handler.
710
+ *
711
+ * Returns buffer.fromstring(tostring(object)).
712
+ */
713
+sol_object_t *sol_f_default_tobuffer(sol_state_t *, sol_object_t *);
707 714
 
708 715
 /// Built-in function toint
709 716
 sol_object_t *sol_f_toint(sol_state_t *, sol_object_t *);
@@ -711,6 +718,8 @@ sol_object_t *sol_f_toint(sol_state_t *, sol_object_t *);
711 718
 sol_object_t *sol_f_tofloat(sol_state_t *, sol_object_t *);
712 719
 /// Built-in function tostring
713 720
 sol_object_t *sol_f_tostring(sol_state_t *, sol_object_t *);
721
+/// Built-in function tobuffer
722
+sol_object_t *sol_f_tobuffer(sol_state_t *, sol_object_t *);
714 723
 /// Built-in function try
715 724
 sol_object_t *sol_f_try(sol_state_t *, sol_object_t *);
716 725
 /// Built-in function apply
@@ -748,8 +757,10 @@ sol_object_t *sol_f_debug_closure(sol_state_t *, sol_object_t *);
748 757
 sol_object_t *sol_f_debug_globals(sol_state_t *, sol_object_t *);
749 758
 sol_object_t *sol_f_debug_locals(sol_state_t *, sol_object_t *);
750 759
 sol_object_t *sol_f_debug_scopes(sol_state_t *, sol_object_t *);
760
+sol_object_t *sol_f_debug_getops(sol_state_t *, sol_object_t *);
751 761
 
752 762
 sol_object_t *sol_f_iter_str(sol_state_t *, sol_object_t *);
763
+sol_object_t *sol_f_iter_buffer(sol_state_t *, sol_object_t *);
753 764
 sol_object_t *sol_f_iter_list(sol_state_t *, sol_object_t *);
754 765
 sol_object_t *sol_f_iter_map(sol_state_t *, sol_object_t *);
755 766
 
@@ -759,6 +770,7 @@ sol_object_t *sol_f_readline_add_history(sol_state_t *, sol_object_t *);
759 770
 sol_object_t *sol_f_ast_print(sol_state_t *, sol_object_t *);
760 771
 
761 772
 sol_object_t *sol_f_singlet_tostring(sol_state_t *, sol_object_t *);
773
+sol_object_t *sol_f_singlet_tobuffer(sol_state_t *, sol_object_t *);
762 774
 
763 775
 sol_object_t *sol_f_int_add(sol_state_t *, sol_object_t *);
764 776
 sol_object_t *sol_f_int_sub(sol_state_t *, sol_object_t *);
@@ -796,6 +808,7 @@ sol_object_t *sol_f_str_index(sol_state_t *, sol_object_t *);
796 808
 sol_object_t *sol_f_str_toint(sol_state_t *, sol_object_t *);
797 809
 sol_object_t *sol_f_str_tofloat(sol_state_t *, sol_object_t *);
798 810
 sol_object_t *sol_f_str_tostring(sol_state_t *, sol_object_t *);
811
+sol_object_t *sol_f_str_tobuffer(sol_state_t *, sol_object_t *);
799 812
 sol_object_t *sol_f_str_repr(sol_state_t *, sol_object_t *);
800 813
 
801 814
 sol_object_t *sol_f_str_sub(sol_state_t *, sol_object_t *);
@@ -844,12 +857,24 @@ sol_object_t *sol_f_astnode_setindex(sol_state_t *, sol_object_t *);
844 857
 sol_object_t *sol_f_astnode_tostring(sol_state_t *, sol_object_t *);
845 858
 
846 859
 sol_object_t *sol_f_buffer_index(sol_state_t *, sol_object_t *);
860
+sol_object_t *sol_f_buffer_add(sol_state_t *, sol_object_t *);
861
+sol_object_t *sol_f_buffer_mul(sol_state_t *, sol_object_t *);
862
+sol_object_t *sol_f_buffer_cmp(sol_state_t *, sol_object_t *);
863
+sol_object_t *sol_f_buffer_len(sol_state_t *, sol_object_t *);
864
+sol_object_t *sol_f_buffer_iter(sol_state_t *, sol_object_t *);
847 865
 sol_object_t *sol_f_buffer_tostring(sol_state_t *, sol_object_t *);
866
+sol_object_t *sol_f_buffer_repr(sol_state_t *, sol_object_t *);
867
+sol_object_t *sol_f_buffer_toint(sol_state_t *, sol_object_t *);
868
+sol_object_t *sol_f_buffer_tofloat(sol_state_t *, sol_object_t *);
869
+sol_object_t *sol_f_buffer_tobuffer(sol_state_t *, sol_object_t *);
848 870
 
849 871
 sol_object_t *sol_f_buffer_get(sol_state_t *, sol_object_t *);
850 872
 sol_object_t *sol_f_buffer_set(sol_state_t *, sol_object_t *);
851 873
 sol_object_t *sol_f_buffer_address(sol_state_t *, sol_object_t *);
852 874
 sol_object_t *sol_f_buffer_size(sol_state_t *, sol_object_t *);
875
+sol_object_t *sol_f_buffer_sub(sol_state_t *, sol_object_t *);
876
+sol_object_t *sol_f_buffer_split(sol_state_t *, sol_object_t *);
877
+sol_object_t *sol_f_buffer_find(sol_state_t *, sol_object_t *);
853 878
 
854 879
 sol_object_t *sol_f_buffer_new(sol_state_t *, sol_object_t *);
855 880
 sol_object_t *sol_f_buffer_fromstring(sol_state_t *, sol_object_t *);
@@ -875,7 +900,7 @@ sol_object_t *sol_f_stream_index(sol_state_t *, sol_object_t *);
875 900
 sol_object_t *sol_f_stream_tostring(sol_state_t *, sol_object_t *);
876 901
 
877 902
 sol_object_t *sol_f_stream_write(sol_state_t *, sol_object_t *);
878
-sol_object_t *sol_f_stream_read(sol_state_t *, sol_object_t *);
903
+/*sol_object_t *sol_f_stream_read(sol_state_t *, sol_object_t *);*/
879 904
 sol_object_t *sol_f_stream_read_buffer(sol_state_t *, sol_object_t *);
880 905
 sol_object_t *sol_f_stream_seek(sol_state_t *, sol_object_t *);
881 906
 sol_object_t *sol_f_stream_tell(sol_state_t *, sol_object_t *);
@@ -903,6 +928,9 @@ sol_object_t *sol_f_stream_open(sol_state_t *, sol_object_t *);
903 928
 #define sol_is_buffer(obj) ((obj)->type == SOL_BUFFER)
904 929
 #define sol_is_cdata(obj) ((obj)->type == SOL_CDATA)
905 930
 
931
+#define sol_is_name(obj) (sol_is_string(obj) || sol_is_buffer(obj))
932
+#define sol_name_eq(state, obj, cstr) (sol_is_string(obj) ? sol_string_eq((state), (obj), (cstr)) : (sol_is_buffer(obj) ? sol_buffer_eq((state), (obj), (cstr)) : 0))
933
+
906 934
 #define sol_has_error(state) (!sol_is_none((state), (state)->error))
907 935
 
908 936
 /** Creates a new singlet object with the specified name (or NULL).
@@ -1064,6 +1092,11 @@ sol_object_t *sol_new_cfunc(sol_state_t *, sol_cfunc_t, char *);
1064 1092
 sol_object_t *sol_new_cdata(sol_state_t *, void *, sol_ops_t *);
1065 1093
 
1066 1094
 sol_object_t *sol_new_buffer(sol_state_t *, void *, ssize_t, sol_owntype_t, sol_freefunc_t, sol_movefunc_t);
1095
+int sol_buffer_cmp(sol_state_t *, sol_object_t *, const char *);
1096
+#define sol_buffer_eq(state, buffer, cstr) (sol_buffer_cmp((state), (buffer), (cstr)) == 0)
1097
+sol_object_t *sol_buffer_concat(sol_state_t *, sol_object_t *, sol_object_t *);
1098
+sol_object_t *sol_buffer_concat_cstr(sol_state_t *, sol_object_t *, char *);
1099
+char *sol_buffer_strdup(sol_object_t *);
1067 1100
 
1068 1101
 sol_object_t *sol_new_dylib(sol_state_t *, void *);
1069 1102
 
@@ -1099,6 +1132,7 @@ sol_object_t *sol_cast_int(sol_state_t *, sol_object_t *);
1099 1132
 sol_object_t *sol_cast_float(sol_state_t *, sol_object_t *);
1100 1133
 sol_object_t *sol_cast_string(sol_state_t *, sol_object_t *);
1101 1134
 sol_object_t *sol_cast_repr(sol_state_t *, sol_object_t *);
1135
+sol_object_t *sol_cast_buffer(sol_state_t *, sol_object_t *);
1102 1136
 
1103 1137
 sol_object_t *sol_f_singlet_free(sol_state_t *, sol_object_t *);
1104 1138
 sol_object_t *sol_f_str_free(sol_state_t *, sol_object_t *);

+ 29
- 8
state.c View File

@@ -79,6 +79,7 @@ int sol_state_init(sol_state_t *state) {
79 79
 
80 80
 	state->SingletOps.tname = "singlet";
81 81
 	state->SingletOps.tostring = sol_f_singlet_tostring;
82
+	state->SingletOps.tobuffer = sol_f_singlet_tobuffer;
82 83
 	state->SingletOps.free = sol_f_singlet_free;
83 84
 
84 85
 	state->IntOps.tname = "int";
@@ -119,6 +120,7 @@ int sol_state_init(sol_state_t *state) {
119 120
 	state->StringOps.toint = sol_f_str_toint;
120 121
 	state->StringOps.tofloat = sol_f_str_tofloat;
121 122
 	state->StringOps.tostring = sol_f_str_tostring;
123
+	state->StringOps.tobuffer = sol_f_str_tobuffer;
122 124
 	state->StringOps.repr = sol_f_str_repr;
123 125
 	state->StringOps.free = sol_f_str_free;
124 126
 
@@ -169,8 +171,17 @@ int sol_state_init(sol_state_t *state) {
169 171
 	state->ASTNodeOps.free = sol_f_astnode_free;
170 172
 
171 173
 	state->BufferOps.tname = "buffer";
174
+	state->BufferOps.add = sol_f_buffer_add;
175
+	state->BufferOps.mul = sol_f_buffer_mul;
176
+	state->BufferOps.cmp = sol_f_buffer_cmp;
177
+	state->BufferOps.len = sol_f_buffer_len;
178
+	state->BufferOps.iter = sol_f_buffer_iter;
172 179
 	state->BufferOps.index = sol_f_buffer_index;
173 180
 	state->BufferOps.tostring = sol_f_buffer_tostring;
181
+	state->BufferOps.repr = sol_f_buffer_repr;
182
+	state->BufferOps.toint = sol_f_buffer_toint;
183
+	state->BufferOps.tofloat = sol_f_buffer_tofloat;
184
+	state->BufferOps.tobuffer = sol_f_buffer_tobuffer;
174 185
 	state->BufferOps.free = sol_f_buffer_free;
175 186
 
176 187
 	state->DyLibOps.tname = "dylib";
@@ -242,6 +253,7 @@ int sol_state_init(sol_state_t *state) {
242 253
 	sol_map_borrow_name(state, globals, "toint", sol_new_cfunc(state, sol_f_toint, "toint"));
243 254
 	sol_map_borrow_name(state, globals, "tofloat", sol_new_cfunc(state, sol_f_tofloat, "tofloat"));
244 255
 	sol_map_borrow_name(state, globals, "tostring", sol_new_cfunc(state, sol_f_tostring, "tostring"));
256
+	sol_map_borrow_name(state, globals, "tobuffer", sol_new_cfunc(state, sol_f_tobuffer, "tobuffer"));
245 257
 	sol_map_borrow_name(state, globals, "try", sol_new_cfunc(state, sol_f_try, "try"));
246 258
 	sol_map_borrow_name(state, globals, "apply", sol_new_cfunc(state, sol_f_apply, "apply"));
247 259
 	sol_map_borrow_name(state, globals, "error", sol_new_cfunc(state, sol_f_error, "error"));
@@ -265,17 +277,21 @@ int sol_state_init(sol_state_t *state) {
265 277
 	sol_map_borrow_name(state, mod, "globals", sol_new_cfunc(state, sol_f_debug_globals, "debug.globals"));
266 278
 	sol_map_borrow_name(state, mod, "locals", sol_new_cfunc(state, sol_f_debug_locals, "debug.locals"));
267 279
 	sol_map_borrow_name(state, mod, "scopes", sol_new_cfunc(state, sol_f_debug_scopes, "debug.scopes"));
268
-	sol_map_borrow_name(state, mod, "version", sol_new_string(state, SOL_VERSION));
280
+	sol_map_borrow_name(state, mod, "version", sol_new_buffer(state, SOL_VERSION, strlen(SOL_VERSION), OWN_NONE, NULL, NULL));
269 281
 	sol_map_borrow_name(state, mod, "hexversion", sol_new_int(state, SOL_HEXVER));
270 282
 #ifdef SOL_ICACHE
271 283
 	sol_map_borrow_name(state, mod, "icache_min", sol_new_int(state, SOL_ICACHE_MIN));
272 284
 	sol_map_borrow_name(state, mod, "icache_max", sol_new_int(state, SOL_ICACHE_MAX));
273 285
 #endif
286
+	sol_map_borrow_name(state, mod, "modules", state->modules);
287
+	sol_map_borrow_name(state, mod, "methods", state->methods);
288
+	sol_map_borrow_name(state, mod, "getops", sol_new_cfunc(state, sol_f_debug_getops, "debug.getops"));
274 289
 	sol_register_module_name(state, "debug", mod);
275 290
 	sol_obj_free(mod);
276 291
 
277 292
 	mod = sol_new_map(state);
278 293
 	sol_map_borrow_name(state, mod, "str", sol_new_cfunc(state, sol_f_iter_str, "iter.str"));
294
+	sol_map_borrow_name(state, mod, "buffer", sol_new_cfunc(state, sol_f_iter_buffer, "iter.buffer"));
279 295
 	sol_map_borrow_name(state, mod, "list", sol_new_cfunc(state, sol_f_iter_list, "iter.list"));
280 296
 	sol_map_borrow_name(state, mod, "map", sol_new_cfunc(state, sol_f_iter_map, "iter.map"));
281 297
 	sol_register_module_name(state, "iter", mod);
@@ -426,8 +442,8 @@ int sol_state_init(sol_state_t *state) {
426 442
 	sol_map_borrow_name(state, mod, "SEEK_SET", sol_new_int(state, SEEK_SET));
427 443
 	sol_map_borrow_name(state, mod, "SEEK_CUR", sol_new_int(state, SEEK_CUR));
428 444
 	sol_map_borrow_name(state, mod, "SEEK_END", sol_new_int(state, SEEK_END));
429
-	sol_map_borrow_name(state, mod, "ALL", sol_new_string(state, "ALL"));
430
-	sol_map_borrow_name(state, mod, "LINE", sol_new_string(state, "LINE"));
445
+	sol_map_borrow_name(state, mod, "ALL", sol_new_buffer(state, "ALL", 3, OWN_NONE, NULL, NULL));
446
+	sol_map_borrow_name(state, mod, "LINE", sol_new_buffer(state, "LINE", 4, OWN_NONE, NULL, NULL));
431 447
 	sol_map_borrow_name(state, mod, "TIOCGWINSZ", sol_new_int(state, TIOCGWINSZ));
432 448
 	sol_map_borrow_name(state, mod, "TIOCSWINSZ", sol_new_int(state, TIOCSWINSZ));
433 449
 	sol_map_borrow_name(state, mod, "open", sol_new_cfunc(state, sol_f_stream_open, "io.open"));
@@ -441,6 +457,9 @@ int sol_state_init(sol_state_t *state) {
441 457
 	sol_map_borrow_name(state, meths, "set", sol_new_cfunc(state, sol_f_buffer_set, "buffer.set"));
442 458
 	sol_map_borrow_name(state, meths, "address", sol_new_cfunc(state, sol_f_buffer_address, "buffer.address"));
443 459
 	sol_map_borrow_name(state, meths, "size", sol_new_cfunc(state, sol_f_buffer_size, "buffer.size"));
460
+	sol_map_borrow_name(state, meths, "sub", sol_new_cfunc(state, sol_f_buffer_sub, "buffer.sub"));
461
+	sol_map_borrow_name(state, meths, "split", sol_new_cfunc(state, sol_f_buffer_split, "buffer.split"));
462
+	sol_map_borrow_name(state, meths, "find", sol_new_cfunc(state, sol_f_buffer_find, "buffer.find"));
444 463
 	sol_register_methods_name(state, "buffer", meths);
445 464
 	sol_obj_free(meths);
446 465
 
@@ -456,7 +475,7 @@ int sol_state_init(sol_state_t *state) {
456 475
 	sol_obj_free(meths);
457 476
 
458 477
 	meths = sol_new_map(state);
459
-	sol_map_borrow_name(state, meths, "read", sol_new_cfunc(state, sol_f_stream_read, "stream.read"));
478
+	sol_map_borrow_name(state, meths, "read", sol_new_cfunc(state, sol_f_stream_read_buffer, "stream.read_buffer"));
460 479
 	sol_map_borrow_name(state, meths, "read_buffer", sol_new_cfunc(state, sol_f_stream_read_buffer, "stream.read_buffer"));
461 480
 	sol_map_borrow_name(state, meths, "write", sol_new_cfunc(state, sol_f_stream_write, "stream.write"));
462 481
 	sol_map_borrow_name(state, meths, "seek", sol_new_cfunc(state, sol_f_stream_seek, "stream.seek"));
@@ -604,7 +623,7 @@ sol_object_t *sol_state_resolve(sol_state_t *state, sol_object_t *key) {
604 623
 }
605 624
 
606 625
 sol_object_t *sol_state_resolve_name(sol_state_t *state, const char *name) {
607
-	sol_object_t *key = sol_new_string(state, name), *temp;
626
+	sol_object_t *key = sol_new_buffer(state, (char *) name, strlen(name), OWN_NONE, NULL, NULL), *temp;
608 627
 
609 628
 	if(sol_has_error(state)) {
610 629
 		return sol_incref(state->None);
@@ -639,7 +658,7 @@ void sol_state_assign(sol_state_t *state, sol_object_t *key, sol_object_t *val)
639 658
 }
640 659
 
641 660
 void sol_state_assign_name(sol_state_t *state, const char *name, sol_object_t *val) {
642
-	sol_object_t *key = sol_new_string(state, name);
661
+	sol_object_t *key = sol_new_buffer(state, (char *) name, strlen(name), OWN_NONE, NULL, NULL);
643 662
 
644 663
 	if(sol_has_error(state)) {
645 664
 		return;
@@ -668,7 +687,7 @@ void sol_state_assign_l(sol_state_t *state, sol_object_t *key, sol_object_t *val
668 687
 }
669 688
 
670 689
 void sol_state_assign_l_name(sol_state_t *state, const char *name, sol_object_t *val) {
671
-	sol_object_t *key = sol_new_string(state, name);
690
+	sol_object_t *key = sol_new_buffer(state, (char *) name, strlen(name), OWN_NONE, NULL, NULL);
672 691
 
673 692
 	if(sol_has_error(state)) {
674 693
 		return;
@@ -697,9 +716,10 @@ sol_object_t *sol_set_error(sol_state_t *state, sol_object_t *err) {
697 716
 }
698 717
 
699 718
 sol_object_t *sol_set_error_string(sol_state_t *state, const char *serr) {
700
-	sol_object_t *err = sol_new_string(state, serr), *res;
719
+	sol_object_t *err = sol_new_buffer(state, strdup(serr), strlen(serr), OWN_FREE, NULL, NULL), *res;
701 720
 
702 721
 	if(sol_has_error(state)) {
722
+		sol_obj_free(err);
703 723
 		return sol_incref(state->None);
704 724
 	}
705 725
 
@@ -866,6 +886,7 @@ void sol_ops_init(sol_ops_t *ops) {
866 886
 	ops->toint = sol_f_not_impl;
867 887
 	ops->tofloat = sol_f_not_impl;
868 888
 	ops->tostring = sol_f_default_tostring;
889
+	ops->tobuffer = sol_f_default_tobuffer;
869 890
 	ops->repr = sol_f_default_repr;
870 891
 	ops->init = sol_f_no_op;
871 892
 	ops->free = sol_f_no_op;

BIN
tests/crasher_embedded_nul.sol View File


+ 9
- 0
tests/crasher_init_comma.sol View File

@@ -0,0 +1,9 @@
1
+execfile("tests/_lib.sol")
2
+
3
+assert_eq([0], [,,,,0], "initial comma in list")
4
+d = {,,a=7}
5
+assert_eq(d.a, 7, "initial comma in map")
6
+
7
+ident = lambda(,x) x end
8
+
9
+assert_eq("hi", ident(,"hi"), "initial comma in funcdecl/call")

+ 2
- 3
tokenizer.lex View File

@@ -88,9 +88,8 @@ IDENT [a-zA-Z_][a-zA-Z0-9_]*
88 88
 
89 89
 {DIGIT}+ { *yylval = malloc(sizeof(long)); *((long *) *yylval) = atol(yytext); return INT; }
90 90
 
91
-\"[^"]*\" { *yylval = strdup(yytext+1); ((char *) *yylval)[yyleng-2] = 0; return STRING; }
92
-
93
-\'[^']*\' { *yylval = strdup(yytext+1); ((char *) *yylval)[yyleng-2] = 0; return STRING; }
91
+\"[^"]*\"	|
92
+\'[^']*\' { *yylval = malloc(sizeof(unsigned long) + (yyleng - 2) * sizeof(char)); *((unsigned long *) *yylval) = yyleng - 2; memcpy(((char *) *yylval) + sizeof(unsigned long), yytext + 1, yyleng - 2); return STRING; }
94 93
 
95 94
 if { return IF; }
96 95
 

Loading…
Cancel
Save