	SUBROUTINE GET_PROT_CMND_DATA ( memory, dflt_cx, dtype, status )

*  This software was developed by the Thermal Modeling and Analysis
*  Project(TMAP) of the National Oceanographic and Atmospheric
*  Administration's (NOAA) Pacific Marine Environmental Lab(PMEL),
*  hereafter referred to as NOAA/PMEL/TMAP.
*
*  Access and use of this software shall impose the following
*  obligations and understandings on the user. The user is granted the
*  right, without any fee or cost, to use, copy, modify, alter, enhance
*  and distribute this software, and any derivative works thereof, and
*  its supporting documentation for any purpose whatsoever, provided
*  that this entire notice appears in all copies of the software,
*  derivative works and supporting documentation.  Further, the user
*  agrees to credit NOAA/PMEL/TMAP in any publications that result from
*  the use of this software or in any product that includes this
*  software. The names TMAP, NOAA and/or PMEL, however, may not be used
*  in any advertising or publicity to endorse or promote any products
*  or commercial entity unless specific written permission is obtained
*  from NOAA/PMEL/TMAP. The user also understands that NOAA/PMEL/TMAP
*  is not obligated to provide the user with any support, consulting,
*  training or assistance of any kind with regard to the use, operation
*  and performance of this software nor to provide the user with any
*  updates, revisions, new versions or "bug fixes".
*
*  THIS SOFTWARE IS PROVIDED BY NOAA/PMEL/TMAP "AS IS" AND ANY EXPRESS
*  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
*  ARE DISCLAIMED. IN NO EVENT SHALL NOAA/PMEL/TMAP BE LIABLE FOR ANY SPECIAL,
*  INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
*  RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
*  CONTRACT, NEGLIGENCE OR OTHER TORTUOUS ACTION, ARISING OUT OF OR IN
*  CONNECTION WITH THE ACCESS, USE OR PERFORMANCE OF THIS SOFTWARE. 
*
*
* "get protected command data"
* calculate grid(s) of data based on the expression given or implied.
* Expression(s) are in user-variable (uvar) structures.
* Implied expression is left from last command
* when done - return with the variables still "protected" (flagged as in use)

* a sample command may look like:
*	prompt> CONTOUR/Z=50 TEMP[X=160E:160W]
* the "Z=50"		is a "command  qualifier" or "command  context modifier"
* the "X=160E:160W"	is a "variable qualifier" or "variable context modifier"

* contexts are transferred, modified and used in the following manner:
*   i)	skeletal context ( without grid-related info.) is specified in the call
*	Usually it is based on SET REGION,DTA_SET,etc. ( cx_last )
*  ii)	this context is modified by the command qualifiers given to produce a 
*	new skeletal context to be used for the evaluation of the current 
*	command ( cx_cmnd )
*  iii)	as the expression is evaluated each variable, as it is encountered,
*	begins with cx_cmnd and modifies it by the variable
*	qualifiers to produce the context at which the variable is to be
*	evaluated.

* programmer - steve hankin
* NOAA/PMEL, Seattle, WA - Tropical Modeling and Analysis Program

* V230: 7/27/92 - new routine based on GET_CMND_DATA with the unprotecting
* of variables removed to a separate routine
*  (revision history for GET_CMND_DATA shown here)

*   rev 0.0 - 6/17/86
*   rev 1.0 - 1/5/87  - multiple variables in a single expression may be
*			   evaluated and pointers returned in COMMON/XCONTEXT
*   rev 2.0 - 1/5/87  - evaluations done on the INTERPRETATION STACK.  User-
*			   defined variables introduced
*   rev 2.1 - 9/16/87 - added get_cx_only to calling sequence
*			   and unknown_qual_ok moved to FERRET.PARM
*   rev 2.2 - 9/22/87 - shortened code using GET_NEW_cx
*   rev 2.3 - 9/30/87 - added mr_perm_prot
*   rev 2.4 - 7/26/88 - don't pass unstand_grid to last context
*   V200:  5/18/89 - don't pass context on to next command
*	  	   - initialize grid stack pointer
*          8/19/91 - explicit SAVE statement for last expression buffer
* V312: 5/94 - array "memory" as a calling argument
* 12/96 *kob* - Linux Port - had to move variable assignments off of
*               declaration line. used DATA statment rather than a
*	        PARAMETER statement because laslen was modified in code
*	      - Linux F90 doesn't allow SAVE statement, so put an ifdef
*		check around it 
* V500:  1/99 - allowing strings in quoble quotes requires fix to quote
*		handling as in LIST "hello"
*		Added call to ALL_1_ARG
* V530: *sh* 9/00 - added data type ad an argument
*		  - increased size of "last" stored command
* V540: *sh* 11/00 - "last" var init moved to DELETE_OLD_EXPR
* v552: *acm* 4/03   Increase length of variable names to 128 characters
* V600 *acm* 3/06  fixing bugs 439&1390, new arg to get_new_cx.
* V690 *sh* 12/13  manage auto-curvilinear mode
*	           aux vars returned on the ISP stack in frame above is_aux_ptr

	include 'tmap_dims.parm'
	include	'ferret.parm'
	include 'errmsg.parm'
	include 'interp_stack.parm'
	include 'xcontext.cmn'
	include 'xvariables.cmn'
	include 'xprog_state.cmn'
	include 'xfr_grid.cmn'

* calling argument declarations
	INTEGER	dflt_cx, dtype, status
	REAL	memory(*) 

* local variable declarations
	LOGICAL		auto_auxvar_changed
	INTEGER		TM_LENSTR1, nu, cx_expr, idim
	CHARACTER	EXPR_NAME*8, VAR_CODE*128, buff*128

* initialize grid stack pointer (pushes down from top)
	grd_stk_ptr = max_grids

* initialize aux stack frames at top of isp stack
	max_usable_intrp = max_intrp
	max_context = max_noframe_context  ! just to be clear (not needed)

* determine if in auto-curvilinear mode
	CALL SET_AUTO_CURVI_MODES( auto_auxvar_changed )

* delete any memory left-overs from last command
	CALL DELETE_MRS_IN_PROGRESS

* * * * DETERMINE CONTEXT FOR COMMAND * * *
	CALL GET_NEW_CX( dflt_cx, cx_cmnd, .TRUE., status )
	IF ( status .NE. ferr_ok ) GOTO 5000

* consolidate arguments broken up by command parser back into a single arg
* ... correct mis-handling of surrounding quotation marks
	CALL ALL_1_ARG

* * * * BREAK FULL EXPRESSION INTO SUB_EXPRESSIONS * * *
* ... and store them in the uvar list names as "EX#n"
* ... eg. LIST U^2,V^2 breaks into "U^2" and "V^2"
* ... or re-use the last expression ?
	IF ( num_args .GT. 0 
     .  .OR. auto_auxvar_changed ) THEN
	   IF ( last_cmnd_buff(:len_last_cmnd)
     .     .NE.      cmnd_buff(arg_start(1):arg_end(1)) 
     .	   .OR. num_uvars_in_cmnd .EQ. cmnd_uvars_not_given
     .	   .OR. auto_auxvar_changed 		) THEN
	      CALL DELETE_OLD_EXPR
	      last_cmnd_buff = cmnd_buff(arg_start(1):arg_end(1))
	      len_last_cmnd  = arg_end(1) - arg_start(1) + 1
	      CALL BREAK_UP_EXPR( cmnd_buff(arg_start(1):arg_end(1)),
     .				  num_uvars_in_cmnd, status )
	      IF ( status .NE. ferr_ok ) THEN
	         num_uvars_in_cmnd = cmnd_uvars_not_given
	         GOTO 5000
	      ENDIF
	   ENDIF
	ENDIF

* * * * EVALUATE THE SUB-EXPRESSIONS * * *
	IF ( num_uvars_in_cmnd .EQ. cmnd_uvars_not_given )
     .		CALL ERRMSG
     .			(ferr_invalid_command,status,'no data specified',*5000)

	DO 300 nu = 1, num_uvars_in_cmnd

* ... a context slot to hold a fresh command context for each sub-expression
	   cx_stack_ptr = cx_stack_ptr + 1
	   cx_expr = cx_stack_ptr

* ... a frame of size nferdims to hold aux vars needed for plotting and listing
	   max_usable_intrp = max_usable_intrp - nferdims
	   max_context      = max_context      - nferdims
	   DO idim = 1, nferdims
	      is_mr(max_usable_intrp+idim) = unspecified_int4
	      is_cx(max_usable_intrp+idim) = unspecified_int4  ! bookkeeping
	   ENDDO

* ... evaluate the next sub-expression
	   CALL TRANSFER_CONTEXT( cx_cmnd, cx_expr )
	   CALL INTERP_STACK( memory, nu, cx_expr,
     .			      EXPR_NAME(nu), status )
	   IF ( status .NE. ferr_ok ) GOTO 5000

* check for legal data type
	   IF ( dtype .NE. ptype_native ) THEN
	      IF (mr_type(is_mr(isp)) .NE. dtype ) GOTO 5100
	   ENDIF

* tag the result for what it is
* note that since aux vars may now be returned on the ISP stack, isp may be GT nu
	   is_act(isp) = isact_var_ready

! temp diagnostic
	   IF ( cx_stack_ptr .NE. cx_cmnd+nu ) WRITE (6,*) 'get_cmnd_???'
 300	CONTINUE

* turn off oversizing flag for next command
	cx_ovsiz(dflt_cx) = ovsiz_off
	RETURN

* error exit
 5000	RETURN
 5100	buff = VAR_CODE(mr_category(is_mr(nu)),mr_variable(is_mr(nu)))
* ... copied from INTERP_STACK error exit ... probably over-kill
	CALL RELEASE_WORK_SPC
        CALL DELETE_MRS_IN_PROGRESS
        CALL UNPROTECT_ALL_MRS
        CALL DEALLO_ALL_GRIDS
        CALL CLEAN_STACK
	CALL ERRMSG( ferr_data_type, status,buff(:TM_LENSTR1(buff)), *5000 )
	END
