aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2019-01-25 14:24:03 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2019-02-14 14:40:57 +0100
commit5c6b9165e776f60b7bfeb01a2d5fa6331ee0cb89 (patch)
tree6e5770c2b8fbc28d7d43934d79d6c28e3eeec205
parent8296334c1f457c598e04e1aa0f79cbdbbba27427 (diff)
downloadbusybox-w32-5c6b9165e776f60b7bfeb01a2d5fa6331ee0cb89.tar.gz
busybox-w32-5c6b9165e776f60b7bfeb01a2d5fa6331ee0cb89.tar.bz2
busybox-w32-5c6b9165e776f60b7bfeb01a2d5fa6331ee0cb89.zip
bc: implement pass-by-reference code from upstream
function old new delta zxc_program_popResultAndCopyToVar 298 493 +195 bc_vec_pushIndex - 75 +75 zxc_vm_process 859 928 +69 xc_program_dereference - 66 +66 bc_vec_npush - 65 +65 zbc_num_s 239 249 +10 zxc_program_num 1024 1032 +8 zbc_num_divmod 150 156 +6 xc_program_search 143 146 +3 zxc_program_assign 392 389 -3 zdc_program_execStr 520 517 -3 xc_program_pushVar 198 195 -3 zxc_program_exec 4101 4092 -9 zbc_program_call 318 308 -10 zbc_func_insert 120 104 -16 zbc_parse_stmt_possibly_auto 1460 1439 -21 bc_vec_push 53 12 -41 xc_parse_pushIndex 61 18 -43 ------------------------------------------------------------------------------ (add/remove: 3/0 grow/shrink: 6/9 up/down: 497/-149) Total: 348 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--miscutils/bc.c271
-rw-r--r--testsuite/bc_references.bc106
-rw-r--r--testsuite/bc_references_results.txt212
3 files changed, 503 insertions, 86 deletions
diff --git a/miscutils/bc.c b/miscutils/bc.c
index 8e0069658..a8b4332c1 100644
--- a/miscutils/bc.c
+++ b/miscutils/bc.c
@@ -4,8 +4,8 @@
4 * Adapted from https://github.com/gavinhoward/bc 4 * Adapted from https://github.com/gavinhoward/bc
5 * Original code copyright (c) 2018 Gavin D. Howard and contributors. 5 * Original code copyright (c) 2018 Gavin D. Howard and contributors.
6 */ 6 */
7//TODO: GNU extensions: 7//TODO:
8// support "define f(*param[])" - "pass array by reference" syntax 8// maybe implement a^b for non-integer b?
9 9
10#define DEBUG_LEXER 0 10#define DEBUG_LEXER 0
11#define DEBUG_COMPILE 0 11#define DEBUG_COMPILE 0
@@ -380,6 +380,12 @@ typedef struct BcInstPtr {
380 size_t inst_idx; 380 size_t inst_idx;
381} BcInstPtr; 381} BcInstPtr;
382 382
383typedef enum BcType {
384 BC_TYPE_VAR,
385 BC_TYPE_ARRAY,
386 BC_TYPE_REF,
387} BcType;
388
383typedef enum BcLexType { 389typedef enum BcLexType {
384 XC_LEX_EOF, 390 XC_LEX_EOF,
385 XC_LEX_INVALID, 391 XC_LEX_INVALID,
@@ -1092,15 +1098,25 @@ static void bc_vec_pop_all(BcVec *v)
1092 bc_vec_npop(v, v->len); 1098 bc_vec_npop(v, v->len);
1093} 1099}
1094 1100
1095static size_t bc_vec_push(BcVec *v, const void *data) 1101static size_t bc_vec_npush(BcVec *v, size_t n, const void *data)
1096{ 1102{
1097 size_t len = v->len; 1103 size_t len = v->len;
1098 if (len >= v->cap) bc_vec_grow(v, 1); 1104 if (len + n > v->cap) bc_vec_grow(v, n);
1099 memmove(v->v + (v->size * len), data, v->size); 1105 memmove(v->v + (v->size * len), data, v->size * n);
1100 v->len++; 1106 v->len = len + n;
1101 return len; 1107 return len;
1102} 1108}
1103 1109
1110static size_t bc_vec_push(BcVec *v, const void *data)
1111{
1112 return bc_vec_npush(v, 1, data);
1113 //size_t len = v->len;
1114 //if (len >= v->cap) bc_vec_grow(v, 1);
1115 //memmove(v->v + (v->size * len), data, v->size);
1116 //v->len = len + 1;
1117 //return len;
1118}
1119
1104// G.prog.results often needs "pop old operand, push result" idiom. 1120// G.prog.results often needs "pop old operand, push result" idiom.
1105// Can do this without a few extra ops 1121// Can do this without a few extra ops
1106static size_t bc_result_pop_and_push(const void *data) 1122static size_t bc_result_pop_and_push(const void *data)
@@ -3528,14 +3544,14 @@ static void xc_parse_pushName(char *name)
3528// (The above describes 32-bit case). 3544// (The above describes 32-bit case).
3529#define SMALL_INDEX_LIMIT (0x100 - sizeof(size_t)) 3545#define SMALL_INDEX_LIMIT (0x100 - sizeof(size_t))
3530 3546
3531static void xc_parse_pushIndex(size_t idx) 3547static void bc_vec_pushIndex(BcVec *v, size_t idx)
3532{ 3548{
3533 size_t mask; 3549 size_t mask;
3534 unsigned amt; 3550 unsigned amt;
3535 3551
3536 dbg_lex("%s:%d pushing index %zd", __func__, __LINE__, idx); 3552 dbg_lex("%s:%d pushing index %zd", __func__, __LINE__, idx);
3537 if (idx < SMALL_INDEX_LIMIT) { 3553 if (idx < SMALL_INDEX_LIMIT) {
3538 xc_parse_push(idx); 3554 bc_vec_pushByte(v, idx);
3539 return; 3555 return;
3540 } 3556 }
3541 3557
@@ -3548,14 +3564,19 @@ static void xc_parse_pushIndex(size_t idx)
3548 } 3564 }
3549 // amt is at least 1 here - "one byte of length data follows" 3565 // amt is at least 1 here - "one byte of length data follows"
3550 3566
3551 xc_parse_push((SMALL_INDEX_LIMIT - 1) + amt); 3567 bc_vec_pushByte(v, (SMALL_INDEX_LIMIT - 1) + amt);
3552 3568
3553 do { 3569 do {
3554 xc_parse_push((unsigned char)idx); 3570 bc_vec_pushByte(v, (unsigned char)idx);
3555 idx >>= 8; 3571 idx >>= 8;
3556 } while (idx != 0); 3572 } while (idx != 0);
3557} 3573}
3558 3574
3575static void xc_parse_pushIndex(size_t idx)
3576{
3577 bc_vec_pushIndex(&G.prs.func->code, idx);
3578}
3579
3559static void xc_parse_pushInst_and_Index(unsigned inst, size_t idx) 3580static void xc_parse_pushInst_and_Index(unsigned inst, size_t idx)
3560{ 3581{
3561 xc_parse_push(inst); 3582 xc_parse_push(inst);
@@ -4340,7 +4361,7 @@ static BC_STATUS zbc_parse_break_or_continue(BcLexType type)
4340} 4361}
4341#define zbc_parse_break_or_continue(...) (zbc_parse_break_or_continue(__VA_ARGS__) COMMA_SUCCESS) 4362#define zbc_parse_break_or_continue(...) (zbc_parse_break_or_continue(__VA_ARGS__) COMMA_SUCCESS)
4342 4363
4343static BC_STATUS zbc_func_insert(BcFunc *f, char *name, bool var) 4364static BC_STATUS zbc_func_insert(BcFunc *f, char *name, BcType type)
4344{ 4365{
4345 BcId *autoid; 4366 BcId *autoid;
4346 BcId a; 4367 BcId a;
@@ -4349,13 +4370,13 @@ static BC_STATUS zbc_func_insert(BcFunc *f, char *name, bool var)
4349 autoid = (void*)f->autos.v; 4370 autoid = (void*)f->autos.v;
4350 for (i = 0; i < f->autos.len; i++, autoid++) { 4371 for (i = 0; i < f->autos.len; i++, autoid++) {
4351 if (strcmp(name, autoid->name) == 0 4372 if (strcmp(name, autoid->name) == 0
4352 && var == autoid->idx 4373 && type == (BcType) autoid->idx
4353 ) { 4374 ) {
4354 RETURN_STATUS(bc_error("duplicate function parameter or auto name")); 4375 RETURN_STATUS(bc_error("duplicate function parameter or auto name"));
4355 } 4376 }
4356 } 4377 }
4357 4378
4358 a.idx = var; 4379 a.idx = type;
4359 a.name = name; 4380 a.name = name;
4360 4381
4361 bc_vec_push(&f->autos, &a); 4382 bc_vec_push(&f->autos, &a);
@@ -4368,7 +4389,7 @@ static BC_STATUS zbc_parse_funcdef(void)
4368{ 4389{
4369 BcParse *p = &G.prs; 4390 BcParse *p = &G.prs;
4370 BcStatus s; 4391 BcStatus s;
4371 bool var, comma, voidfunc; 4392 bool comma, voidfunc;
4372 char *name; 4393 char *name;
4373 4394
4374 dbg_lex_enter("%s:%d entered", __func__, __LINE__); 4395 dbg_lex_enter("%s:%d entered", __func__, __LINE__);
@@ -4406,6 +4427,16 @@ static BC_STATUS zbc_parse_funcdef(void)
4406 4427
4407 comma = false; 4428 comma = false;
4408 while (p->lex != BC_LEX_RPAREN) { 4429 while (p->lex != BC_LEX_RPAREN) {
4430 BcType t = BC_TYPE_VAR;
4431
4432 if (p->lex == XC_LEX_OP_MULTIPLY) {
4433 t = BC_TYPE_REF;
4434 s = zxc_lex_next();
4435 if (s) RETURN_STATUS(s);
4436 s = zbc_POSIX_does_not_allow("references");
4437 if (s) RETURN_STATUS(s);
4438 }
4439
4409 if (p->lex != XC_LEX_NAME) 4440 if (p->lex != XC_LEX_NAME)
4410 RETURN_STATUS(bc_error_bad_function_definition()); 4441 RETURN_STATUS(bc_error_bad_function_definition());
4411 4442
@@ -4415,9 +4446,8 @@ static BC_STATUS zbc_parse_funcdef(void)
4415 s = zxc_lex_next(); 4446 s = zxc_lex_next();
4416 if (s) goto err; 4447 if (s) goto err;
4417 4448
4418 var = p->lex != BC_LEX_LBRACKET; 4449 if (p->lex == BC_LEX_LBRACKET) {
4419 4450 if (t == BC_TYPE_VAR) t = BC_TYPE_ARRAY;
4420 if (!var) {
4421 s = zxc_lex_next(); 4451 s = zxc_lex_next();
4422 if (s) goto err; 4452 if (s) goto err;
4423 4453
@@ -4429,6 +4459,10 @@ static BC_STATUS zbc_parse_funcdef(void)
4429 s = zxc_lex_next(); 4459 s = zxc_lex_next();
4430 if (s) goto err; 4460 if (s) goto err;
4431 } 4461 }
4462 else if (t == BC_TYPE_REF) {
4463 s = bc_error_at("vars can't be references");
4464 goto err;
4465 }
4432 4466
4433 comma = p->lex == BC_LEX_COMMA; 4467 comma = p->lex == BC_LEX_COMMA;
4434 if (comma) { 4468 if (comma) {
@@ -4436,7 +4470,7 @@ static BC_STATUS zbc_parse_funcdef(void)
4436 if (s) goto err; 4470 if (s) goto err;
4437 } 4471 }
4438 4472
4439 s = zbc_func_insert(p->func, name, var); 4473 s = zbc_func_insert(p->func, name, t);
4440 if (s) goto err; 4474 if (s) goto err;
4441 } 4475 }
4442 4476
@@ -4488,7 +4522,7 @@ static BC_STATUS zbc_parse_auto(void)
4488 if (s) RETURN_STATUS(s); 4522 if (s) RETURN_STATUS(s);
4489 4523
4490 for (;;) { 4524 for (;;) {
4491 bool var; 4525 BcType t;
4492 4526
4493 if (p->lex != XC_LEX_NAME) 4527 if (p->lex != XC_LEX_NAME)
4494 RETURN_STATUS(bc_error_at("bad 'auto' syntax")); 4528 RETURN_STATUS(bc_error_at("bad 'auto' syntax"));
@@ -4497,8 +4531,9 @@ static BC_STATUS zbc_parse_auto(void)
4497 s = zxc_lex_next(); 4531 s = zxc_lex_next();
4498 if (s) goto err; 4532 if (s) goto err;
4499 4533
4500 var = (p->lex != BC_LEX_LBRACKET); 4534 t = BC_TYPE_VAR;
4501 if (!var) { 4535 if (p->lex == BC_LEX_LBRACKET) {
4536 t = BC_TYPE_ARRAY;
4502 s = zxc_lex_next(); 4537 s = zxc_lex_next();
4503 if (s) goto err; 4538 if (s) goto err;
4504 4539
@@ -4510,7 +4545,7 @@ static BC_STATUS zbc_parse_auto(void)
4510 if (s) goto err; 4545 if (s) goto err;
4511 } 4546 }
4512 4547
4513 s = zbc_func_insert(p->func, name, var); 4548 s = zbc_func_insert(p->func, name, t);
4514 if (s) goto err; 4549 if (s) goto err;
4515 4550
4516 if (p->lex == XC_LEX_NLINE 4551 if (p->lex == XC_LEX_NLINE
@@ -5119,12 +5154,64 @@ static BC_STATUS zdc_parse_exprs_until_eof(void)
5119#define STACK_HAS_MORE_THAN(s, n) ((s)->len > ((size_t)(n))) 5154#define STACK_HAS_MORE_THAN(s, n) ((s)->len > ((size_t)(n)))
5120#define STACK_HAS_EQUAL_OR_MORE_THAN(s, n) ((s)->len >= ((size_t)(n))) 5155#define STACK_HAS_EQUAL_OR_MORE_THAN(s, n) ((s)->len >= ((size_t)(n)))
5121 5156
5122static BcVec* xc_program_search(char *id, bool var) 5157static size_t xc_program_index(char *code, size_t *bgn)
5158{
5159 unsigned char *bytes = (void*)(code + *bgn);
5160 unsigned amt;
5161 unsigned i;
5162 size_t res;
5163
5164 amt = *bytes++;
5165 if (amt < SMALL_INDEX_LIMIT) {
5166 *bgn += 1;
5167 return amt;
5168 }
5169 amt -= (SMALL_INDEX_LIMIT - 1); // amt is 1 or more here
5170 *bgn += amt + 1;
5171
5172 res = 0;
5173 i = 0;
5174 do {
5175 res |= (size_t)(*bytes++) << i;
5176 i += 8;
5177 } while (--amt != 0);
5178
5179 return res;
5180}
5181
5182static char *xc_program_name(char *code, size_t *bgn)
5183{
5184 code += *bgn;
5185 *bgn += strlen(code) + 1;
5186
5187 return xstrdup(code);
5188}
5189
5190static BcVec* xc_program_dereference(BcVec *vec)
5191{
5192 BcVec *v;
5193 size_t vidx, nidx, i = 0;
5194
5195 //assert(vec->size == sizeof(uint8_t));
5196
5197 vidx = xc_program_index(vec->v, &i);
5198 nidx = xc_program_index(vec->v, &i);
5199
5200 v = bc_vec_item(&G.prog.arrs, vidx);
5201 v = bc_vec_item(v, nidx);
5202
5203 //assert(v->size != sizeof(uint8_t));
5204
5205 return v;
5206}
5207
5208static BcVec* xc_program_search(char *id, BcType type)
5123{ 5209{
5124 BcId e, *ptr; 5210 BcId e, *ptr;
5125 BcVec *v, *map; 5211 BcVec *v, *map;
5126 size_t i; 5212 size_t i;
5127 int new; 5213 int new;
5214 bool var = (type == BC_TYPE_VAR);
5128 5215
5129 v = var ? &G.prog.vars : &G.prog.arrs; 5216 v = var ? &G.prog.vars : &G.prog.arrs;
5130 map = var ? &G.prog.var_map : &G.prog.arr_map; 5217 map = var ? &G.prog.var_map : &G.prog.arr_map;
@@ -5178,17 +5265,20 @@ static BC_STATUS zxc_program_num(BcResult *r, BcNum **num)
5178 case XC_RESULT_VAR: 5265 case XC_RESULT_VAR:
5179 case XC_RESULT_ARRAY: 5266 case XC_RESULT_ARRAY:
5180 case XC_RESULT_ARRAY_ELEM: { 5267 case XC_RESULT_ARRAY_ELEM: {
5181 BcVec *v; 5268 BcType type = (r->t == XC_RESULT_VAR) ? BC_TYPE_VAR : BC_TYPE_ARRAY;
5182 void *p; 5269 BcVec *v = xc_program_search(r->d.id.name, type);
5183 v = xc_program_search(r->d.id.name, r->t == XC_RESULT_VAR); 5270 void *p = bc_vec_top(v);
5184// dc variables are all stacks, so here we have this: 5271
5185 p = bc_vec_top(v);
5186// TODO: eliminate these stacks for bc-only config?
5187 if (r->t == XC_RESULT_ARRAY_ELEM) { 5272 if (r->t == XC_RESULT_ARRAY_ELEM) {
5273 size_t idx = r->d.id.idx;
5274
5188 v = p; 5275 v = p;
5189 if (v->len <= r->d.id.idx) 5276 if (v->size == sizeof(uint8_t))
5190 bc_array_expand(v, r->d.id.idx + 1); 5277 v = xc_program_dereference(v);
5191 *num = bc_vec_item(v, r->d.id.idx); 5278 //assert(v->size == sizeof(BcNum));
5279 if (v->len <= idx)
5280 bc_array_expand(v, idx + 1);
5281 *num = bc_vec_item(v, idx);
5192 } else { 5282 } else {
5193 *num = p; 5283 *num = p;
5194 } 5284 }
@@ -5347,39 +5437,6 @@ static BC_STATUS zxc_program_read(void)
5347} 5437}
5348#define zxc_program_read(...) (zxc_program_read(__VA_ARGS__) COMMA_SUCCESS) 5438#define zxc_program_read(...) (zxc_program_read(__VA_ARGS__) COMMA_SUCCESS)
5349 5439
5350static size_t xc_program_index(char *code, size_t *bgn)
5351{
5352 unsigned char *bytes = (void*)(code + *bgn);
5353 unsigned amt;
5354 unsigned i;
5355 size_t res;
5356
5357 amt = *bytes++;
5358 if (amt < SMALL_INDEX_LIMIT) {
5359 *bgn += 1;
5360 return amt;
5361 }
5362 amt -= (SMALL_INDEX_LIMIT - 1); // amt is 1 or more here
5363 *bgn += amt + 1;
5364
5365 res = 0;
5366 i = 0;
5367 do {
5368 res |= (size_t)(*bytes++) << i;
5369 i += 8;
5370 } while (--amt != 0);
5371
5372 return res;
5373}
5374
5375static char *xc_program_name(char *code, size_t *bgn)
5376{
5377 code += *bgn;
5378 *bgn += strlen(code) + 1;
5379
5380 return xstrdup(code);
5381}
5382
5383static void xc_program_printString(const char *str) 5440static void xc_program_printString(const char *str)
5384{ 5441{
5385#if ENABLE_DC 5442#if ENABLE_DC
@@ -5755,43 +5812,81 @@ static BC_STATUS zdc_program_assignStr(BcResult *r, BcVec *v, bool push)
5755#define zdc_program_assignStr(...) (zdc_program_assignStr(__VA_ARGS__) COMMA_SUCCESS) 5812#define zdc_program_assignStr(...) (zdc_program_assignStr(__VA_ARGS__) COMMA_SUCCESS)
5756#endif // ENABLE_DC 5813#endif // ENABLE_DC
5757 5814
5758static BC_STATUS zxc_program_popResultAndCopyToVar(char *name, bool var) 5815static BC_STATUS zxc_program_popResultAndCopyToVar(char *name, BcType t)
5759{ 5816{
5760 BcStatus s; 5817 BcStatus s;
5761 BcResult *ptr, r; 5818 BcResult *ptr, r;
5762 BcVec *v; 5819 BcVec *vec;
5763 BcNum *n; 5820 BcNum *n;
5821 bool var = (t == BC_TYPE_VAR);
5764 5822
5765 if (!STACK_HAS_MORE_THAN(&G.prog.results, 0)) 5823 if (!STACK_HAS_MORE_THAN(&G.prog.results, 0))
5766 RETURN_STATUS(bc_error_stack_has_too_few_elements()); 5824 RETURN_STATUS(bc_error_stack_has_too_few_elements());
5767 5825
5768 ptr = bc_vec_top(&G.prog.results); 5826 ptr = bc_vec_top(&G.prog.results);
5769 if ((ptr->t == XC_RESULT_ARRAY) != !var) 5827 if ((ptr->t == XC_RESULT_ARRAY) == var)
5770 RETURN_STATUS(bc_error_variable_is_wrong_type()); 5828 RETURN_STATUS(bc_error_variable_is_wrong_type());
5771 v = xc_program_search(name, var); 5829 vec = xc_program_search(name, t);
5772 5830
5773#if ENABLE_DC 5831#if ENABLE_DC
5774 if (ptr->t == XC_RESULT_STR && !var) 5832 if (ptr->t == XC_RESULT_STR) {
5775 RETURN_STATUS(bc_error_variable_is_wrong_type()); 5833 if (!var)
5776 if (ptr->t == XC_RESULT_STR) 5834 RETURN_STATUS(bc_error_variable_is_wrong_type());
5777 RETURN_STATUS(zdc_program_assignStr(ptr, v, true)); 5835 RETURN_STATUS(zdc_program_assignStr(ptr, vec, true));
5836 }
5778#endif 5837#endif
5779 5838
5780 s = zxc_program_num(ptr, &n); 5839 s = zxc_program_num(ptr, &n);
5781 if (s) RETURN_STATUS(s); 5840 if (s) RETURN_STATUS(s);
5782 5841
5783 // Do this once more to make sure that pointers were not invalidated. 5842 // Do this once more to make sure that pointers were not invalidated.
5784 v = xc_program_search(name, var); 5843 vec = xc_program_search(name, t);
5785 5844
5786 if (var) { 5845 if (var) {
5787 bc_num_init_DEF_SIZE(&r.d.n); 5846 bc_num_init_DEF_SIZE(&r.d.n);
5788 bc_num_copy(&r.d.n, n); 5847 bc_num_copy(&r.d.n, n);
5789 } else { 5848 } else {
5849 BcVec *v = (BcVec*) n;
5850 bool ref, ref_size;
5851
5852 ref = (v->size == sizeof(BcVec) && t != BC_TYPE_ARRAY);
5853 ref_size = (v->size == sizeof(uint8_t));
5854
5855 if (ref || (ref_size && t == BC_TYPE_REF)) {
5856 bc_vec_init(&r.d.v, sizeof(uint8_t), NULL);
5857 if (ref) {
5858 size_t vidx, idx;
5859 BcId id;
5860
5861 id.name = ptr->d.id.name;
5862 v = xc_program_search(ptr->d.id.name, BC_TYPE_REF);
5863
5864 // Make sure the pointer was not invalidated.
5865 vec = xc_program_search(name, t);
5866
5867 vidx = bc_map_find_exact(&G.prog.arr_map, &id);
5868 //assert(vidx != BC_VEC_INVALID_IDX);
5869 vidx = ((BcId*) bc_vec_item(&G.prog.arr_map, vidx))->idx;
5870 idx = v->len - 1;
5871
5872 bc_vec_pushIndex(&r.d.v, vidx);
5873 bc_vec_pushIndex(&r.d.v, idx);
5874 }
5875 // If we get here, we are copying a ref to a ref.
5876 else bc_vec_npush(&r.d.v, v->len, v->v);
5877
5878 // We need to return early.
5879 goto ret;
5880 }
5881
5882 if (ref_size && t != BC_TYPE_REF)
5883 v = xc_program_dereference(v);
5884
5790 bc_array_init(&r.d.v, true); 5885 bc_array_init(&r.d.v, true);
5791 bc_array_copy(&r.d.v, (BcVec *) n); 5886 bc_array_copy(&r.d.v, v);
5792 } 5887 }
5793 5888 ret:
5794 bc_vec_push(v, &r.d); 5889 bc_vec_push(vec, &r.d);
5795 bc_vec_pop(&G.prog.results); 5890 bc_vec_pop(&G.prog.results);
5796 5891
5797 RETURN_STATUS(s); 5892 RETURN_STATUS(s);
@@ -5818,7 +5913,7 @@ static BC_STATUS zxc_program_assign(char inst)
5818 5913
5819 if (left->t != XC_RESULT_VAR) 5914 if (left->t != XC_RESULT_VAR)
5820 RETURN_STATUS(bc_error_variable_is_wrong_type()); 5915 RETURN_STATUS(bc_error_variable_is_wrong_type());
5821 v = xc_program_search(left->d.id.name, true); 5916 v = xc_program_search(left->d.id.name, BC_TYPE_VAR);
5822 5917
5823 RETURN_STATUS(zdc_program_assignStr(right, v, false)); 5918 RETURN_STATUS(zdc_program_assignStr(right, v, false));
5824 } 5919 }
@@ -5897,7 +5992,7 @@ static BC_STATUS xc_program_pushVar(char *code, size_t *bgn,
5897 5992
5898#if ENABLE_DC 5993#if ENABLE_DC
5899 if (pop || copy) { 5994 if (pop || copy) {
5900 BcVec *v = xc_program_search(name, true); 5995 BcVec *v = xc_program_search(name, BC_TYPE_VAR);
5901 BcNum *num = bc_vec_top(v); 5996 BcNum *num = bc_vec_top(v);
5902 5997
5903 free(name); 5998 free(name);
@@ -6014,16 +6109,19 @@ static BC_STATUS zbc_program_call(char *code, size_t *idx)
6014 for (i = 0; i < nparams; ++i) { 6109 for (i = 0; i < nparams; ++i) {
6015 BcResult *arg; 6110 BcResult *arg;
6016 BcStatus s; 6111 BcStatus s;
6112 bool arr;
6017 6113
6018 a = bc_vec_item(&func->autos, nparams - 1 - i); 6114 a = bc_vec_item(&func->autos, nparams - 1 - i);
6019 arg = bc_vec_top(&G.prog.results); 6115 arg = bc_vec_top(&G.prog.results);
6020 6116
6021 if ((!a->idx) != (arg->t == XC_RESULT_ARRAY) // array/variable mismatch 6117 arr = (a->idx == BC_TYPE_ARRAY || a->idx == BC_TYPE_REF);
6118
6119 if (arr != (arg->t == XC_RESULT_ARRAY) // array/variable mismatch
6022 // || arg->t == XC_RESULT_STR - impossible, f("str") is not a legal syntax (strings are not bc expressions) 6120 // || arg->t == XC_RESULT_STR - impossible, f("str") is not a legal syntax (strings are not bc expressions)
6023 ) { 6121 ) {
6024 RETURN_STATUS(bc_error_variable_is_wrong_type()); 6122 RETURN_STATUS(bc_error_variable_is_wrong_type());
6025 } 6123 }
6026 s = zxc_program_popResultAndCopyToVar(a->name, a->idx); 6124 s = zxc_program_popResultAndCopyToVar(a->name, (BcType) a->idx);
6027 if (s) RETURN_STATUS(s); 6125 if (s) RETURN_STATUS(s);
6028 } 6126 }
6029 6127
@@ -6031,12 +6129,13 @@ static BC_STATUS zbc_program_call(char *code, size_t *idx)
6031 for (; i < func->autos.len; i++, a++) { 6129 for (; i < func->autos.len; i++, a++) {
6032 BcVec *v; 6130 BcVec *v;
6033 6131
6034 v = xc_program_search(a->name, a->idx); 6132 v = xc_program_search(a->name, (BcType) a->idx);
6035 if (a->idx) { 6133 if (a->idx == BC_TYPE_VAR) {
6036 BcNum n2; 6134 BcNum n2;
6037 bc_num_init_DEF_SIZE(&n2); 6135 bc_num_init_DEF_SIZE(&n2);
6038 bc_vec_push(v, &n2); 6136 bc_vec_push(v, &n2);
6039 } else { 6137 } else {
6138 //assert(a->idx == BC_TYPE_ARRAY);
6040 BcVec v2; 6139 BcVec v2;
6041 bc_array_init(&v2, true); 6140 bc_array_init(&v2, true);
6042 bc_vec_push(v, &v2); 6141 bc_vec_push(v, &v2);
@@ -6087,7 +6186,7 @@ static BC_STATUS zbc_program_return(char inst)
6087 a = (void*)f->autos.v; 6186 a = (void*)f->autos.v;
6088 for (i = 0; i < f->autos.len; i++, a++) { 6187 for (i = 0; i < f->autos.len; i++, a++) {
6089 BcVec *v; 6188 BcVec *v;
6090 v = xc_program_search(a->name, a->idx); 6189 v = xc_program_search(a->name, (BcType) a->idx);
6091 bc_vec_pop(v); 6190 bc_vec_pop(v);
6092 } 6191 }
6093 6192
@@ -6399,7 +6498,7 @@ static BC_STATUS zdc_program_execStr(char *code, size_t *bgn, bool cond)
6399 6498
6400 if (exec) { 6499 if (exec) {
6401 BcVec *v; 6500 BcVec *v;
6402 v = xc_program_search(name, true); 6501 v = xc_program_search(name, BC_TYPE_VAR);
6403 n = bc_vec_top(v); 6502 n = bc_vec_top(v);
6404 } 6503 }
6405 6504
@@ -6724,7 +6823,7 @@ static BC_STATUS zxc_program_exec(void)
6724 } 6823 }
6725 case DC_INST_PUSH_TO_VAR: { 6824 case DC_INST_PUSH_TO_VAR: {
6726 char *name = xc_program_name(code, &ip->inst_idx); 6825 char *name = xc_program_name(code, &ip->inst_idx);
6727 s = zxc_program_popResultAndCopyToVar(name, true); 6826 s = zxc_program_popResultAndCopyToVar(name, BC_TYPE_VAR);
6728 free(name); 6827 free(name);
6729 break; 6828 break;
6730 } 6829 }
diff --git a/testsuite/bc_references.bc b/testsuite/bc_references.bc
new file mode 100644
index 000000000..fc48c1a56
--- /dev/null
+++ b/testsuite/bc_references.bc
@@ -0,0 +1,106 @@
1define printarray(a[], len) {
2
3 auto i
4
5 for (i = 0; i < len; ++i) {
6 a[i]
7 }
8}
9
10define a2(a[], len) {
11
12 auto i
13
14 for (i = 0; i < len; ++i) {
15 a[i] = a[i] * a[i]
16 }
17
18 printarray(a[], len)
19}
20
21define a4(a__[], len) {
22
23 auto i
24
25 for (i = 0; i < len; ++i) {
26 a__[i] = a__[i] * a__[i]
27 }
28
29 printarray(a__[], len)
30}
31
32define a6(*a__[], len) {
33
34 auto i
35
36 for (i = 0; i < len; ++i) {
37 a__[i] = a__[i] * a__[i]
38 }
39
40 printarray(a__[], len)
41}
42
43define a1(*a[], len) {
44
45 auto i
46
47 for (i = 0; i < len; ++i) {
48 a[i] = i
49 }
50
51 a2(a[], len)
52
53 printarray(a[], len)
54}
55
56define a3(*a__[], len) {
57
58 auto i
59
60 for (i = 0; i < len; ++i) {
61 a__[i] = i
62 }
63
64 a4(a__[], len)
65
66 printarray(a__[], len)
67}
68
69define a5(*a__[], len) {
70
71 auto i
72
73 for (i = 0; i < len; ++i) {
74 a__[i] = i
75 }
76
77 a2(a__[], len)
78
79 printarray(a__[], len)
80}
81
82define a7(*a__[], len) {
83
84 auto i
85
86 for (i = 0; i < len; ++i) {
87 a__[i] = i
88 }
89
90 a6(a__[], len)
91
92 printarray(a__[], len)
93}
94
95len = 16
96
97a1(a[], len)
98printarray(a[], len)
99a3(a[], len)
100printarray(a[], len)
101a5(a[], len)
102printarray(a[], len)
103a7(a[], len)
104printarray(a[], len)
105
106halt
diff --git a/testsuite/bc_references_results.txt b/testsuite/bc_references_results.txt
new file mode 100644
index 000000000..564b54a3a
--- /dev/null
+++ b/testsuite/bc_references_results.txt
@@ -0,0 +1,212 @@
10
21
34
49
516
625
736
849
964
1081
11100
12121
13144
14169
15196
16225
170
180
190
201
212
223
234
245
256
267
278
289
2910
3011
3112
3213
3314
3415
350
360
370
381
392
403
414
425
436
447
458
469
4710
4811
4912
5013
5114
5215
530
540
551
564
579
5816
5925
6036
6149
6264
6381
64100
65121
66144
67169
68196
69225
700
710
720
731
742
753
764
775
786
797
808
819
8210
8311
8412
8513
8614
8715
880
890
900
911
922
933
944
955
966
977
988
999
10010
10111
10212
10313
10414
10515
1060
1070
1081
1094
1109
11116
11225
11336
11449
11564
11681
117100
118121
119144
120169
121196
122225
1230
1240
1250
1261
1272
1283
1294
1305
1316
1327
1338
1349
13510
13611
13712
13813
13914
14015
1410
1420
1430
1441
1452
1463
1474
1485
1496
1507
1518
1529
15310
15411
15512
15613
15714
15815
1590
1600
1611
1624
1639
16416
16525
16636
16749
16864
16981
170100
171121
172144
173169
174196
175225
1760
1770
1780
1791
1804
1819
18216
18325
18436
18549
18664
18781
188100
189121
190144
191169
192196
193225
1940
1950
1960
1971
1984
1999
20016
20125
20236
20349
20464
20581
206100
207121
208144
209169
210196
211225
2120