diff --git a/src/asm/resolver/eval_fn.rs b/src/asm/resolver/eval_fn.rs index 52e91f47..b0aa8067 100644 --- a/src/asm/resolver/eval_fn.rs +++ b/src/asm/resolver/eval_fn.rs @@ -115,6 +115,26 @@ pub fn eval_fn( } +fn ensure_inc_args( + query: &mut expr::EvalFunctionQuery +) -> Result<(),()> +{ + if query.args.len() < 1 || query.args.len() > 3 + { + query.report.error_span( + format!("function expected 1 to 3 arguments (got {})", query.args.len()), + query.span + ); + + Err(()) + } + else + { + Ok(()) + } +} + + fn eval_builtin_incbin( fileserver: &mut dyn util::FileServer, _decls: &asm::ItemDecls, @@ -123,7 +143,7 @@ fn eval_builtin_incbin( query: &mut expr::EvalFunctionQuery) -> Result { - query.ensure_arg_number(1)?; + ensure_inc_args(query)?; let relative_filename = query.args[0].value.expect_string( query.report, @@ -148,8 +168,53 @@ fn eval_builtin_incbin( Some(query.args[0].span), file_handle)?; - Ok(expr::Value::make_integer( - util::BigInt::from_bytes_be(&bytes))) + if query.args.len() == 1 { + Ok(expr::Value::make_integer( + util::BigInt::from_bytes_be(&bytes))) + } else if query.args.len() == 2 { + let start = query.args[1].value.expect_usize(query.report, query.args[1].span)?; + + if start >= bytes.len() { + query.report.error_span( + format!("incbin starts after EOF ({} > {})", + start, + bytes.len()), + query.args[1].span + ); + return Err(()); + } + + Ok(expr::Value::make_integer( + util::BigInt::from_bytes_be(&bytes[start..bytes.len()]))) + } else { + let start = query.args[1].value.expect_usize(query.report, query.args[1].span)?; + + let size = query.args[2].value.expect_usize(query.report, query.args[2].span)?; + + if start >= bytes.len() { + query.report.error_span( + format!("incbin starts after EOF ({} > {})", + start, + bytes.len()), + query.args[1].span + ); + return Err(()); + } + + if (start+size) > bytes.len() { + query.report.error_span( + format!("incbin ends after EOF ({} + {} > {})", + start, + size, + bytes.len()), + query.args[2].span + ); + return Err(()); + } + + Ok(expr::Value::make_integer( + util::BigInt::from_bytes_be(&bytes[start..(start+size)]))) + } } @@ -259,4 +324,4 @@ fn eval_builtin_incstr( } Ok(expr::Value::make_integer(bitvec.to_bigint())) -} \ No newline at end of file +}