f_getbufvar(typval_T *argvars, typval_T *rettv)
{
    buf_T	*buf;
    char_u	*varname;
    dictitem_T	*v;
    int		done = FALSE;

    if (in_vim9script()
	    && (check_for_buffer_arg(argvars, 0) == FAIL
		|| check_for_string_arg(argvars, 1) == FAIL))
	return;

    varname = tv_get_string_chk(&argvars[1]);
    buf = tv_get_buf_from_arg(&argvars[0]);

    rettv->v_type = VAR_STRING;
    rettv->vval.v_string = NULL;

    if (buf != NULL && varname != NULL)
    {
	if (*varname == '&')
	{
	    buf_T	*save_curbuf = curbuf;

	    // set curbuf to be our buf, temporarily
	    curbuf = buf;

	    if (varname[1] == NUL)
	    {
		// get all buffer-local options in a dict
		dict_T	*opts = get_winbuf_options(TRUE);

		if (opts != NULL)
		{
		    rettv_dict_set(rettv, opts);
		    done = TRUE;
		}
	    }
	    else if (eval_option(&varname, rettv, TRUE) == OK)
		// buffer-local-option
		done = TRUE;

	    // restore previous notion of curbuf
	    curbuf = save_curbuf;
	}
	else
	{
	    // Look up the variable.
	    if (*varname == NUL)
		// Let getbufvar({nr}, "") return the "b:" dictionary.
		v = &buf->b_bufvar;
	    else
		v = find_var_in_ht(&buf->b_vars->dv_hashtab, 'b',
							       varname, FALSE);
	    if (v != NULL)
	    {
		copy_tv(&v->di_tv, rettv);
		done = TRUE;
	    }
	}
    }

    if (!done && argvars[2].v_type != VAR_UNKNOWN)
	// use the default value
	copy_tv(&argvars[2], rettv);
}
f_getbufvar(typval_T *argvars, typval_T *rettv)
{
    buf_T	*buf;
    char_u	*varname;
    dictitem_T	*v;
    int		done = FALSE;

    if (in_vim9script()
	    && (check_for_buffer_arg(argvars, 0) == FAIL
		|| check_for_string_arg(argvars, 1) == FAIL))
	return;

    varname = tv_get_string_chk(&argvars[1]);
    buf = tv_get_buf_from_arg(&argvars[0]);

    rettv->v_type = VAR_STRING;
    rettv->vval.v_string = NULL;

    if (buf != NULL && varname != NULL)
    {
	if (*varname == '&')
	{
	    buf_T	*save_curbuf = curbuf;

	     
	    curbuf = buf;

	    if (varname[1] == NUL)
	    {
		 
		dict_T	*opts = get_winbuf_options(TRUE);

		if (opts != NULL)
		{
		    rettv_dict_set(rettv, opts);
		    done = TRUE;
		}
	    }
	    else if (eval_option(&varname, rettv, TRUE) == OK)
		 
		done = TRUE;

	     
	    curbuf = save_curbuf;
	}
	else
	{
	     
	    if (*varname == NUL)
		 
		v = &buf->b_bufvar;
	    else
		v = find_var_in_ht(&buf->b_vars->dv_hashtab, 'b',
							       varname, FALSE);
	    if (v != NULL)
	    {
		copy_tv(&v->di_tv, rettv);
		done = TRUE;
	    }
	}
    }

    if (!done && argvars[2].v_type != VAR_UNKNOWN)
	 
	copy_tv(&argvars[2], rettv);
}