001: /*
002: * ProcCmd.java
003: *
004: * Copyright (c) 1997 Cornell University.
005: * Copyright (c) 1997 Sun Microsystems, Inc.
006: *
007: * See the file "license.terms" for information on usage and
008: * redistribution of this file, and for a DISCLAIMER OF ALL
009: * WARRANTIES.
010: *
011: * RCS: @(#) $Id: ProcCmd.java,v 1.6 2005/11/21 01:14:17 mdejong Exp $
012: *
013: */
014:
015: package tcl.lang;
016:
017: /**
018: * This class implements the built-in "proc" command in Tcl.
019: */
020:
021: class ProcCmd implements Command {
022: /**
023: *
024: * Tcl_ProcObjCmd -> ProcCmd.cmdProc
025: *
026: * Creates a new Tcl procedure.
027: *
028: * @param interp the current interpreter.
029: * @param objv command arguments.
030: * @exception TclException If incorrect number of arguments.
031: */
032:
033: public void cmdProc(Interp interp, TclObject[] objv)
034: throws TclException {
035: Procedure proc;
036: String fullName;
037: Command cmd;
038: FindCommandNamespaceResult result;
039:
040: if (objv.length != 4) {
041: throw new TclNumArgsException(interp, 1, objv,
042: "name args body");
043: }
044:
045: // Determine the namespace where the procedure should reside. Unless
046: // the command name includes namespace qualifiers, this will be the
047: // current namespace.
048:
049: fullName = objv[1].toString();
050: result = FindCommandNamespace(interp, fullName);
051:
052: // Create the data structure to represent the procedure.
053:
054: proc = new Procedure(interp, result.ns, result.cmdName,
055: objv[2], objv[3], interp.getScriptFile(), interp
056: .getArgLineNumber(3));
057:
058: // Now create a command for the procedure. This will be in
059: // the current namespace unless the procedure's name included namespace
060: // qualifiers. To create the new command in the right namespace, we
061: // use fully qualified name for it.
062:
063: interp.createCommand(result.cmdFullName, proc);
064:
065: // Now initialize the new procedure's cmdPtr field. This will be used
066: // later when the procedure is called to determine what namespace the
067: // procedure will run in. This will be different than the current
068: // namespace if the proc was renamed into a different namespace.
069:
070: WrappedCommand wcmd = Namespace.findCommand(interp,
071: result.cmdFullName, result.ns, TCL.NAMESPACE_ONLY);
072: proc.wcmd = wcmd;
073:
074: return;
075: }
076:
077: // Helper class used to return namespace lookup results for
078: // a command name.
079:
080: static class FindCommandNamespaceResult {
081: String fullName; // Initial name of command: like "foo" or "::one::two::foo"
082: String cmdName; // Result short name of command: like "foo"
083: String cmdFullName; // Result full name of command: like "::one::two::foo"
084: Namespace ns; // Result namespace the command lives in
085: }
086:
087: // Helper used to lookup the namespace and associated info for a command.
088: // Use when defining a new command.
089:
090: static FindCommandNamespaceResult FindCommandNamespace(
091: Interp interp, String fullName) throws TclException {
092: String procName;
093: Namespace ns, altNs, cxtNs;
094: StringBuffer ds;
095:
096: Namespace.GetNamespaceForQualNameResult gnfqnr = interp.getnfqnResult;
097: Namespace.getNamespaceForQualName(interp, fullName, null, 0,
098: gnfqnr);
099:
100: ns = gnfqnr.ns;
101: altNs = gnfqnr.altNs;
102: cxtNs = gnfqnr.actualCxt;
103: procName = gnfqnr.simpleName;
104:
105: if (ns == null) {
106: throw new TclException(interp, "can't create procedure \""
107: + fullName + "\": unknown namespace");
108: }
109: if (procName == null) {
110: throw new TclException(interp, "can't create procedure \""
111: + fullName + "\": bad procedure name");
112: }
113: // FIXME : could there be a problem with a command named ":command" ?
114: if ((ns != Namespace.getGlobalNamespace(interp))
115: && (procName != null)
116: && ((procName.length() > 0) && (procName.charAt(0) == ':'))) {
117: throw new TclException(
118: interp,
119: "can't create procedure \""
120: + procName
121: + "\" in non-global namespace with name starting with \":\"");
122: }
123:
124: // Return the command info, if the command is defined in a namespace
125: // other than the global namespace then cmdFullName will be the
126: // fully qualified name for the command.
127:
128: ds = new StringBuffer();
129: if (ns != Namespace.getGlobalNamespace(interp)) {
130: ds.append(ns.fullName);
131: ds.append("::");
132: }
133: ds.append(procName);
134:
135: FindCommandNamespaceResult result = new FindCommandNamespaceResult();
136: result.fullName = fullName;
137: result.cmdName = procName;
138: result.cmdFullName = ds.toString();
139: result.ns = ns;
140:
141: return result;
142: }
143: }
|