/*
 * VariableCmd.java
 *
 * Copyright (c) 1987-1994 The Regents of the University of California.
 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
 * Copyright (c) 1998-1999 by Scriptics Corporation.
 * Copyright (c) 1999      by Moses DeJong.
 *
 * See the file "license.terms" for information on usage and
 * redistribution of this file, and for a DISCLAIMER OF ALL
 * WARRANTIES.
 *
 * RCS: @(#) $Id: VariableCmd.java,v 1.3 1999/06/30 00:13:39 mo Exp $
 */

package tcl.lang;

/**
 * This class implements the built-in "variable" command in Tcl.
 */

class VariableCmd implements Command {

/*
 *----------------------------------------------------------------------
 *
 * VariableCmd --
 *
 *	Invoked to implement the "variable" command that creates one or more
 *	global variables. Handles the following syntax:
 *
 *	    variable ?name value...? name ?value?
 *
 *	One or more variables can be created. The variables are initialized
 *	with the specified values. The value for the last variable is
 *	optional.
 *
 *	If the variable does not exist, it is created and given the optional
 *	value. If it already exists, it is simply set to the optional
 *	value. Normally, "name" is an unqualified name, so it is created in
 *	the current namespace. If it includes namespace qualifiers, it can
 *	be created in another namespace.
 *
 *	If the variable command is executed inside a Tcl procedure, it
 *	creates a local variable linked to the newly-created namespace
 *	variable.
 *
 * Results:
 *	Returns TCL_OK if the variable is found or created. Returns
 *	TCL_ERROR if anything goes wrong.
 *
 * Side effects:
 *	If anything goes wrong, this procedure returns an error message
 *	as the result in the interpreter's result object.
 *
 *----------------------------------------------------------------------
 */

    public void cmdProc(Interp interp, TclObject[] objv) throws TclException {

	/*
	// FIXME : unimplemented.	 

	throw new TclException(interp, "variable command is not yet implemented");

	*/

	String varName;
	int tail, cp;
	Var var, array;
	TclObject varValue;
	int i;

	for (i = 1;  i < objv.length;  i = i+2) {
	    // Look up each variable in the current namespace context, creating
	    // it if necessary.
	
	    varName = objv[i].toString();
	    Var[] result = Var.lookupVar(interp, varName, null,
		  (TCL.NAMESPACE_ONLY | TCL.LEAVE_ERR_MSG), "define",
		  true, false);
	    if (result == null) {
		// FIXME:
		throw new TclException(interp, "");
	    }

	    var = result[0];
	    array = result[1];

	    // Mark the variable as a namespace variable and increment its 
	    // reference count so that it will persist until its namespace is
	    // destroyed or until the variable is unset.

	    if ((var.flags & Var.NAMESPACE_VAR) == 0) {
		var.flags |= Var.NAMESPACE_VAR;
		var.refCount++;
	    }

	    // If a value was specified, set the variable to that value.
	    // Otherwise, if the variable is new, leave it undefined.
	    // (If the variable already exists and no value was specified,
	    // leave its value unchanged; just create the local link if
	    // we're in a Tcl procedure).

	    if (i+1 < objv.length) {	// a value was specified
		varValue = Var.setVar(interp, objv[i], null, objv[i+1],
				      (TCL.NAMESPACE_ONLY | TCL.LEAVE_ERR_MSG));

		if (varValue == null) {
		    // FIXME:
		    throw new TclException(interp, "");
		}
	    }



	    // If we are executing inside a Tcl procedure, create a local
	    // variable linked to the new namespace variable "varName".

	    if ((interp.varFrame != null)
		&& interp.varFrame.isProcCallFrame) {

		// varName might have a scope qualifier, but the name for the
		// local "link" variable must be the simple name at the tail.
		//
		// Locate tail in one pass: drop any prefix after two *or more*
		// consecutive ":" characters).

		int len = varName.length();

		for (tail = cp = 0; cp < len ; ) {
		    if (varName.charAt(cp++) == ':') {
			while ((cp < len) && (varName.charAt(cp++) == ':')) {
			    tail = cp;
			}
		    }
		}
	    
		// Create a local link "tail" to the variable "varName" in the
		// current namespace.
	    
		Var.makeUpvar(interp, null,
			  varName, null, TCL.NAMESPACE_ONLY,
			  varName.substring(tail), 0);
	    }
	}
    }
}
