wasCSharpSQLite – Blame information for rev

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 #undef DEBUG
2 /*
3 * Procedure.java --
4 *
5 * This class implements the body of a Tcl procedure.
6 *
7 * Copyright (c) 1997 Cornell University.
8 * Copyright (c) 1997 Sun Microsystems, Inc.
9 *
10 * See the file "license.terms" for information on usage and
11 * redistribution of this file, and for a DISCLAIMER OF ALL
12 * WARRANTIES.
13 *
14 * Included in SQLite3 port to C# for use in testharness only; 2008 Noah B Hart
15 *
16 * RCS @(#) $Id: Procedure.java,v 1.4 1999/08/05 03:40:31 mo Exp $
17 *
18 */
19 using System;
20 namespace tcl.lang
21 {
22  
23 /// <summary> This class implements the body of a Tcl procedure.</summary>
24  
25 public class Procedure : Command, CommandWithDispose
26 {
27  
28 // The formal parameters of the procedure and their default values.
29 // argList[0][0] = name of the 1st formal param
30 // argList[0][1] = if non-null, default value of the 1st formal param
31  
32  
33 internal TclObject[][] argList;
34  
35 // True if this proc takes an variable number of arguments. False
36 // otherwise.
37  
38 internal bool isVarArgs;
39  
40 // The body of the procedure.
41  
42 internal CharPointer body;
43 internal int body_length;
44  
45 // The namespace that the Command is defined in
46 internal NamespaceCmd.Namespace ns;
47  
48 // Name of the source file that contains this procedure. May be null, which
49 // indicates that the source file is unknown.
50  
51 internal string srcFileName;
52  
53 // Position where the body of the procedure starts in the source file.
54 // 1 means the first line in the source file.
55  
56 internal int srcLineNumber;
57  
58 internal Procedure( Interp interp, NamespaceCmd.Namespace ns, string name, TclObject args, TclObject b, string sFileName, int sLineNumber )
59 {
60 this.ns = ns;
61 srcFileName = sFileName;
62 srcLineNumber = sLineNumber;
63  
64 // Break up the argument list into argument specifiers, then process
65 // each argument specifier.
66  
67 int numArgs = TclList.getLength( interp, args );
68 argList = new TclObject[numArgs][];
69 for ( int i = 0; i < numArgs; i++ )
70 {
71 argList[i] = new TclObject[2];
72 }
73  
74 for ( int i = 0; i < numArgs; i++ )
75 {
76 // Now divide the specifier up into name and default.
77  
78 TclObject argSpec = TclList.index( interp, args, i );
79 int specLen = TclList.getLength( interp, argSpec );
80  
81 if ( specLen == 0 )
82 {
83 throw new TclException( interp, "procedure \"" + name + "\" has argument with no name" );
84 }
85 if ( specLen > 2 )
86 {
87  
88 throw new TclException( interp, "too many fields in argument " + "specifier \"" + argSpec + "\"" );
89 }
90  
91 argList[i][0] = TclList.index( interp, argSpec, 0 );
92 argList[i][0].preserve();
93 if ( specLen == 2 )
94 {
95 argList[i][1] = TclList.index( interp, argSpec, 1 );
96 argList[i][1].preserve();
97 }
98 else
99 {
100 argList[i][1] = null;
101 }
102 }
103  
104  
105 if ( numArgs > 0 && ( argList[numArgs - 1][0].ToString().Equals( "args" ) ) )
106 {
107 isVarArgs = true;
108 }
109 else
110 {
111 isVarArgs = false;
112 }
113  
114  
115 body = new CharPointer( b.ToString() );
116 body_length = body.length();
117 }
118 public TCL.CompletionCode cmdProc( Interp interp, TclObject[] argv )
119 {
120 // Create the call frame and parameter bindings
121  
122 CallFrame frame = interp.newCallFrame( this, argv );
123  
124 // Execute the body
125  
126 interp.pushDebugStack( srcFileName, srcLineNumber );
127 try
128 {
129 Parser.eval2( interp, body.array, body.index, body_length, 0 );
130 }
131 catch ( TclException e )
132 {
133 TCL.CompletionCode code = e.getCompletionCode();
134 if ( code == TCL.CompletionCode.RETURN )
135 {
136 TCL.CompletionCode realCode = interp.updateReturnInfo();
137 if ( realCode != TCL.CompletionCode.OK )
138 {
139 e.setCompletionCode( realCode );
140 throw;
141 }
142 }
143 else if ( code == TCL.CompletionCode.ERROR )
144 {
145  
146 interp.addErrorInfo( "\n (procedure \"" + argv[0] + "\" line " + interp.errorLine + ")" );
147 throw;
148 }
149 else if ( code == TCL.CompletionCode.BREAK )
150 {
151 throw new TclException( interp, "invoked \"break\" outside of a loop" );
152 }
153 else if ( code == TCL.CompletionCode.CONTINUE )
154 {
155 throw new TclException( interp, "invoked \"continue\" outside of a loop" );
156 }
157 else
158 {
159 throw;
160 }
161 }
162 finally
163 {
164 interp.popDebugStack();
165  
166 // The check below is a hack. The problem is that there
167 // could be unset traces on the variables, which cause
168 // scripts to be evaluated. This will clear the
169 // errInProgress flag, losing stack trace information if
170 // the procedure was exiting with an error. The code
171 // below preserves the flag. Unfortunately, that isn't
172 // really enough: we really should preserve the errorInfo
173 // variable too (otherwise a nested error in the trace
174 // script will trash errorInfo). What's really needed is
175 // a general-purpose mechanism for saving and restoring
176 // interpreter state.
177  
178 if ( interp.errInProgress )
179 {
180 frame.dispose();
181 interp.errInProgress = true;
182 }
183 else
184 {
185 frame.dispose();
186 }
187 }
188 return TCL.CompletionCode.RETURN;
189 }
190 public void disposeCmd()
191 {
192 //body.release();
193 body = null;
194 for ( int i = 0; i < argList.Length; i++ )
195 {
196 argList[i][0].release();
197 argList[i][0] = null;
198  
199 if ( argList[i][1] != null )
200 {
201 argList[i][1].release();
202 argList[i][1] = null;
203 }
204 }
205 argList = null;
206 }
207  
208 internal static bool isProc( WrappedCommand cmd )
209 {
210 return ( cmd.cmd is Procedure );
211  
212 /*
213 // FIXME: do we really want to get the original command
214 // and test that? Methods like InfoCmd.InfoProcsCmd seem
215 // to do this already.
216  
217 WrappedCommand origCmd;
218  
219 origCmd = NamespaceCmd.getOriginalCommand(cmd);
220 if (origCmd != null) {
221 cmd = origCmd;
222 }
223 return (cmd.cmd instanceof Procedure);
224 */
225 }
226  
227 internal static Procedure findProc( Interp interp, string procName )
228 {
229 WrappedCommand cmd;
230 WrappedCommand origCmd;
231  
232 try
233 {
234 cmd = NamespaceCmd.findCommand( interp, procName, null, 0 );
235 }
236 catch ( TclException e )
237 {
238 // This should never happen
239 throw new TclRuntimeError( "unexpected TclException: " + e.Message );
240 }
241  
242 if ( cmd == null )
243 {
244 return null;
245 }
246  
247 origCmd = NamespaceCmd.getOriginalCommand( cmd );
248 if ( origCmd != null )
249 {
250 cmd = origCmd;
251 }
252 if ( !( cmd.cmd is Procedure ) )
253 {
254 return null;
255 }
256 return (Procedure)cmd.cmd;
257 }
258 } // end Procedure
259 }