diff --git a/src/exprlib.c b/src/exprlib.c index 64bd7f3..f3f0b0c 100644 --- a/src/exprlib.c +++ b/src/exprlib.c @@ -492,7 +492,7 @@ static value_t expr_ident ( vm_t *vm, value_t p[], int np ) return result; } -static value_t action_gettext ( vm_t *vm, value_t p[], gint np ) +static value_t expr_gettext ( vm_t *vm, value_t p[], gint np ) { vm_param_check_np_range(vm, np, 1, 2, "GT"); vm_param_check_string(vm, p, 0, "GT"); @@ -503,7 +503,7 @@ static value_t action_gettext ( vm_t *vm, value_t p[], gint np ) np==2? value_get_string(p[1]) : "sfwbar", value_get_string(p[0])))); } -static value_t action_array_build ( vm_t *vm, value_t p[], gint np ) +static value_t expr_array_build ( vm_t *vm, value_t p[], gint np ) { GArray *array; value_t v1; @@ -521,13 +521,13 @@ static value_t action_array_build ( vm_t *vm, value_t p[], gint np ) return value_new_array(array); } -static value_t action_array_index ( vm_t *vm, value_t p[], gint np ) +static value_t expr_array_index ( vm_t *vm, value_t p[], gint np ) { vm_param_check_np(vm, np, 2, "ArrayIndex"); vm_param_check_array(vm, p, 0, "ArrayIndex"); vm_param_check_numeric(vm, p, 1, "ArrayIndex"); - if(!value_is_array(p[0]) || + if(!value_is_array(p[0]) || (gint)value_get_numeric(p[1])<0 || p[0].value.array->len <= ((gint)value_get_numeric(p[1]))) return value_na; @@ -535,9 +535,10 @@ static value_t action_array_index ( vm_t *vm, value_t p[], gint np ) (gint)value_get_numeric(p[1])); } -static value_t action_array_assign ( vm_t *vm, value_t p[], gint np ) +static value_t expr_array_assign ( vm_t *vm, value_t p[], gint np ) { - value_t *v1, varr; + value_t *v1; + GArray *arr; gint n; vm_param_check_np(vm, np, 3, "ArrayAssign"); @@ -547,16 +548,30 @@ static value_t action_array_assign ( vm_t *vm, value_t p[], gint np ) if(!value_is_array(p[0])) return value_na; - varr = value_dup(p[0]); + arr = g_array_ref(p[0].value.array); n = (gint)value_get_numeric(p[1]); - if(p[0].value.array->len <= n) - g_array_set_size(varr.value.array, n+1); + if(n<0 || n>=arr->len) + g_array_set_size(arr, n+1); - v1 = &g_array_index(varr.value.array, value_t, n); + v1 = &g_array_index(arr, value_t, n); value_free(*v1); *v1 = value_dup(p[2]); - return varr; + return value_new_array(arr); +} + +static value_t expr_array_concat ( vm_t *vm, value_t p[], gint np ) +{ + vm_param_check_np(vm, np, 2, "ArrayConcat"); + + return value_array_concat(p[0], p[1]); +} + +static value_t expr_array_size ( vm_t *vm, value_t p[], gint np ) +{ + vm_param_check_np(vm, np, 1, "ArraySize"); + + return value_new_numeric(value_is_array(p[0])? p[0].value.array->len : 0); } void expr_lib_init ( void ) @@ -588,8 +603,10 @@ void expr_lib_init ( void ) vm_func_add("windowinfo", expr_lib_window_info, FALSE); vm_func_add("read", expr_lib_read, FALSE); vm_func_add("interfaceprovider", expr_iface_provider, FALSE); - vm_func_add("gt", action_gettext, FALSE); - vm_func_add("arraybuild", action_array_build, FALSE); - vm_func_add("arrayindex", action_array_index, FALSE); - vm_func_add("arrayassign", action_array_assign, FALSE); + vm_func_add("gt", expr_gettext, FALSE); + vm_func_add("arraybuild", expr_array_build, FALSE); + vm_func_add("arrayindex", expr_array_index, FALSE); + vm_func_add("arrayassign", expr_array_assign, FALSE); + vm_func_add("arrayconcat", expr_array_concat, FALSE); + vm_func_add("arraysize", expr_array_size, FALSE); } diff --git a/src/vm/parser.c b/src/vm/parser.c index afbc4dc..c561694 100644 --- a/src/vm/parser.c +++ b/src/vm/parser.c @@ -242,10 +242,9 @@ static gboolean parser_identifier ( GScanner *scanner, GByteArray *code ) return TRUE; } -static gboolean parser_list_handle ( GScanner *scanner, GByteArray *code ) +static gboolean parser_array_handle ( GScanner *scanner, GByteArray *code ) { - guint8 data[sizeof(gpointer)+2], np = 0; - gconstpointer ptr; + guint8 np = 0; if(g_scanner_peek_next_token(scanner)!=']') do { @@ -257,11 +256,7 @@ static gboolean parser_list_handle ( GScanner *scanner, GByteArray *code ) if(!config_expect_token(scanner, ']', "Expected ']' at the end of the list")) return FALSE; - data[0]=EXPR_OP_FUNCTION; - data[1]=np; - ptr = vm_func_lookup("arraybuild"); - memcpy(data+2, &ptr, sizeof(gpointer)); - g_byte_array_append(code, data, sizeof(gpointer)+2); + parser_emit_function(code, vm_func_lookup("arraybuild"), np); return TRUE; } @@ -280,7 +275,7 @@ static gboolean parser_value ( GScanner *scanner, GByteArray *code ) else if(token == G_TOKEN_STRING) parser_emit_string(code, scanner->value.v_string); else if(token == '[') - parser_list_handle(scanner, code); + parser_array_handle(scanner, code); else if(token == G_TOKEN_IDENTIFIER) return parser_identifier(scanner, code); else if(token == '+') @@ -429,7 +424,6 @@ static gboolean parser_action_parse ( GScanner *scanner, GByteArray *code ) { gconstpointer ptr; gboolean neg; - guint8 data[sizeof(gpointer)+2]; static guint8 discard = EXPR_OP_DISCARD; gint alen, flag, cond = 0, np = 0; @@ -457,11 +451,7 @@ static gboolean parser_action_parse ( GScanner *scanner, GByteArray *code ) parser_emit_numeric(code, cond & 0xff); parser_emit_numeric(code, cond>>8); - ptr = vm_func_lookup("checkstate"); - memcpy(data+2, &ptr, sizeof(gpointer)); - data[0]=EXPR_OP_FUNCTION; - data[1]=2; - g_byte_array_append(code, data, sizeof(gpointer)+2); + parser_emit_function(code, vm_func_lookup("checkstate"), 2); alen = parser_emit_jump(code, EXPR_OP_JZ); } @@ -478,9 +468,6 @@ static gboolean parser_action_parse ( GScanner *scanner, GByteArray *code ) if(!cond && parser_local_lookup(scanner)) return parser_assign_parse(scanner, code); -/* if(!cond && scanner->token==G_TOKEN_IDENTIFIER && - g_scanner_peek_next_token(scanner)=='=') - return parser_assign_parse(scanner, code);*/ if( !config_lookup_next_key(scanner, config_toplevel_keys) && !config_lookup_next_key(scanner, config_prop_keys) && @@ -499,10 +486,7 @@ static gboolean parser_action_parse ( GScanner *scanner, GByteArray *code ) config_check_and_consume(scanner, ';'); - memcpy(data+2, &ptr, sizeof(gpointer)); - data[0]=EXPR_OP_FUNCTION; - data[1]=np; - g_byte_array_append(code, data, sizeof(gpointer)+2); + parser_emit_function(code, ptr, np); if(cond) { diff --git a/src/vm/value.c b/src/vm/value.c index 51ae705..93fa0cd 100644 --- a/src/vm/value.c +++ b/src/vm/value.c @@ -9,6 +9,21 @@ void value_free ( value_t v1 ) g_array_unref(v1.value.array); } +value_t value_array_concat ( value_t v1, value_t v2 ) +{ + if(!value_is_array(v1) && !value_is_array(v1)) + return value_na; + + if(!value_is_array(v1)) + return value_new_array(g_array_prepend_vals(g_array_ref(v2.value.array), + &v1, 1)); + if(!value_is_array(v2)) + return value_new_array(g_array_append_vals(g_array_ref(v1.value.array), + &v2, 1)); + return value_new_array(g_array_append_vals(g_array_ref(v1.value.array), + v2.value.array->data, v2.value.array->len)); +} + value_t value_dup_array ( value_t v1 ) { GArray *array; diff --git a/src/vm/value.h b/src/vm/value.h index cb15f2c..5aa85e3 100644 --- a/src/vm/value.h +++ b/src/vm/value.h @@ -48,8 +48,8 @@ extern const value_t value_na; #define value_as_numeric(v) (value_like_numeric(v)? value_get_numeric(v) : \ (value_is_string(v)? g_ascii_strtod(v.value.string, NULL) : 0)) -//#define value_free(v) { if(value_is_string(v)) g_free(v.value.string); } void value_free ( value_t ); value_t value_dup ( value_t ); +value_t value_array_concat ( value_t v1, value_t v2 ); #endif diff --git a/src/vm/vm.c b/src/vm/vm.c index e9fec3e..f359df6 100644 --- a/src/vm/vm.c +++ b/src/vm/vm.c @@ -53,6 +53,9 @@ static gboolean vm_op_binary ( vm_t *vm ) if(value_is_na(v1) && value_is_na(v2)) result = value_na; + else if(value_is_array(v1) || value_is_array(v2)) + result = value_array_concat(v1, v2); + else if(value_like_string(v1) && value_like_string(v2)) { if(op == '+')