wasCSharpSQLite – Blame information for rev
?pathlinks?
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 | } |