function return_status = nc_attput ( ncfile, varname, attribute_name, attval )
% NC_ATTPUT:  put an attribute into a netcdf file
%
% USAGE:  status = nc_attput ( ncfile, varname, attribute_name, attval );
%
% PARAMETERS:
% Input:
%    ncfile:  name of netcdf file being altered
%    varname:  
%        name of variable being altered.  
%        'GLOBAL' or '' denotes a global attribute.
%        If a numeric -1 is passed in, this will also indicate
%        a global attribute.
%    attribute_name:  name of attribute being altered
%    attval:  value of attribute to be written
% Output:
%    status:  -1 for failure, 0 for success
%
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% $Name:  $
% $Id: nc_attput.m,v 1.1 2005/06/29 16:07:00 brian Exp $
% AUTHOR:  johnevans@acm.org
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%





%
% assume failure until success is known
return_status = -1;

if nargin ~= 4
	fprintf ( 2, 'nc_attput:  must have 4 input arguments.\n\n' );
	help nc_attput;
	return
end


%
% Suppress netcdf verbosity.
mexnc('setopts',0);

[ncid, status] =mexnc( 'open', ncfile, nc_write_mode );
if  status < 0 
	ncerror_msg = mexnc ( 'strerror', status );
	fprintf ( 2, 'nc_attput:  mexnc failed on %s with ''write'' mode, (%s).\n\n', ncfile, ncerror_msg );
	return;
end


%
% Put into define mode.
status = mexnc ( 'redef', ncid );
if ( status < 0 )
	ncerror_msg = mexnc ( 'strerror', status );
	fprintf ( 2, ...
	          'nc_attput:  mexnc operation ''redef'' failed on %s (%s).\n\n', ...
	          ncfile, nc_error_msg );
	mexnc ( 'close', ncid );
	return;
end


%
% If the user passed in the name 'GLOBAL' then we need to check
% that 'GLOBAL' is not the name of a variable.  If it is not, then
% the user must have meant global attribute.
%
% Assume at first that the user did not mean a global attribute.  Then
% test all the conditions under which this could be invalidated.
user_intent_is_global=0;
if ( (ischar(varname)) & ( strcmp(lower(varname),'global') | strcmp(lower(varname),'nc_global') ) )
	[varid, status] = mexnc ( 'inq_varid', ncid, varname );
	if ( status == 0 )
		%
		% There ***WAS*** a variable called 'GLOBAL'.  
		% Good thing we checked.
		;
	else
		%
		% There is NO variable called 'global'.
		user_intent_is_global=1;
		varname = 'NC_GLOBAL';
	end
end

%
% -1 is the varid corresponding to NC_GLOBAL.
if ( (isnumeric(varname)) & (varname == -1) )
	user_intent_is_global = 1;
end

%
% I suppose that '' is invalid as a variable name, so
% it could work to signify a global attribute.
if ( (ischar(varname)) & ( strcmp(varname, '') ) )
	varid = -1;
end

if user_intent_is_global
	varid = -1;
	varname = 'NC_GLOBAL';
else
	[varid, status] = mexnc ( 'inq_varid', ncid, varname );
	if ( status ~= 0 )
		ncerror_msg = mexnc ( 'strerror', status );
		fprintf ( 2, ...
		          '%s:  mexnc operation ''inq_varid'' failed on %s (%s).\n\n', ...
		          mfilename, ncfile, ncerror_msg );
		mexnc ( 'close', ncid );
		return;
	end
end

switch class(attval)

	case 'double'
		status = mexnc ( 'put_att_double', ncid, varid, attribute_name, 'double', length(attval), attval);
	case 'single'
		status = mexnc ( 'put_att_float', ncid, varid, attribute_name, 'float', length(attval), attval);
	case 'int32'
		status = mexnc ( 'put_att_int', ncid, varid, attribute_name, 'int', length(attval), attval);
	case 'int16'
		status = mexnc ( 'put_att_short', ncid, varid, attribute_name, 'short', length(attval), attval);
	case 'int8'
		status = mexnc ( 'put_att_schar', ncid, varid, attribute_name, 'byte', length(attval), attval);
	case 'uint8'
		status = mexnc ( 'put_att_uchar', ncid, varid, attribute_name, 'byte', length(attval), attval);
	case 'char'
		status = mexnc ( 'put_att_text', ncid, varid, attribute_name, 'char', length(attval), attval);
	otherwise
		fprintf ( 2, '%s:  attribute class %s is not handled.\n\n', ...
				mfilename, ncfile, ncerror_msg );
		mexnc ( 'close', ncid );
		return;
end



if ( status < 0 )
	ncerror_msg = mexnc ( 'strerror', status );
	fprintf ( 2, ...
	          'nc_attput:  mexnc operation ''put_att_xxx'' failed on %s, %s, %s attribute (%s).\n\n', ...
	          ncfile, varname, attribute_name, ncerror_msg );
	mexnc ( 'close', ncid );
	return;
end



%
% End define mode.
status = mexnc ( 'end_def', ncid );
if ( status < 0 )
	ncerror_msg = mexnc ( 'strerror', status );
	fprintf ( 2, ...
	          'nc_attput:  mexnc operation ''endef'' failed on %s.\n\n', ...
	          ncfile );
	mexnc ( 'close', ncid );
	return;
end


status = mexnc('close',ncid);
if ( status < 0 )
	ncerror_msg = mexnc ( 'strerror', status );
	fprintf ( 2, ...
	          'nc_attput:  mexnc operation ''close'' failed on %s (%s).\n\n', ...
	          ncfile, ncerror_msg );
	return;
end


%
% if we got this far, we must have succeeded.
return_status = 0;
return;
