wasCSharpSQLite – Blame information for rev

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 using System;
2 using System.Text;
3 using Community.CsharpSqlite;
4 using tcl.lang;
5 using ClientData = System.Object;
6 using Tcl_Interp = tcl.lang.Interp;
7 using Tcl_Obj = tcl.lang.TclObject;
8 using System.IO;
9 using System.Diagnostics;
10  
11  
12 class Testing
13 {
14 /*
15 ** 2009 July 17
16 **
17 ** The author disclaims copyright to this source code. In place of
18 ** a legal notice, here is a blessing:
19 **
20 ** May you do good and not evil.
21 ** May you find forgiveness for yourself and forgive others.
22 ** May you share freely, never taking more than you give.
23 **
24 *************************************************************************
25 ** This file contains code to implement the "sqlite" test harness
26 ** which runs TCL commands for testing the C#-SQLite port.
27 **
28 ** Included in SQLite3 port to C#-SQLite; 2008 Noah B Hart
29 ** C#-SQLite is an independent reimplementation of the SQLite software library
30 **
31 *************************************************************************
32 */
33 public static void Main( string[] args )
34 {
35 // Array of command-line argument strings.
36 {
37 string fileName = null;
38  
39 // Create the interpreter. This will also create the built-in
40 // Tcl commands.
41  
42 Interp interp = new Interp();
43  
44 // Make command-line arguments available in the Tcl variables "argc"
45 // and "argv". If the first argument doesn't start with a "-" then
46 // strip it off and use it as the name of a script file to process.
47 // We also set the argv0 and TCL.Tcl_interactive vars here.
48  
49 if ( ( args.Length > 0 ) && !( args[0].StartsWith( "-" ) ) )
50 {
51 fileName = args[0];
52 }
53  
54 TclObject argv = TclList.newInstance();
55 argv.preserve();
56 try
57 {
58 int i = 0;
59 int argc = args.Length;
60 if ( (System.Object)fileName == null )
61 {
62 interp.setVar( "argv0", "tcl.lang.Shell", TCL.VarFlag.GLOBAL_ONLY );
63 interp.setVar( "tcl_interactive", "1", TCL.VarFlag.GLOBAL_ONLY );
64 }
65 else
66 {
67 interp.setVar( "argv0", fileName, TCL.VarFlag.GLOBAL_ONLY );
68 interp.setVar( "tcl_interactive", "0", TCL.VarFlag.GLOBAL_ONLY );
69 i++;
70 argc--;
71 }
72 for ( ; i < args.Length; i++ )
73 {
74 TclList.append( interp, argv, TclString.newInstance( args[i] ) );
75 }
76 interp.setVar( "argv", argv, TCL.VarFlag.GLOBAL_ONLY );
77 interp.setVar( "argc", System.Convert.ToString( argc ), TCL.VarFlag.GLOBAL_ONLY );
78 }
79 catch ( TclException e )
80 {
81 throw new TclRuntimeError( "unexpected TclException: " + e.Message );
82 }
83 finally
84 {
85 argv.release();
86 }
87  
88 init_all( interp );
89 TCL.Tcl_CreateObjCommand( interp, "load_testfixture_extensions", init_all_cmd, 0, null );
90  
91  
92 // Normally we would do application specific initialization here.
93 // However, that feature is not currently supported.
94 // If a script file was specified then just source that file
95 // and quit.
96  
97 Console.WriteLine( " C#-SQLite version " + Sqlite3.sqlite3_version );
98 Console.WriteLine( "An independent reimplementation of the SQLite software library" );
99 Console.WriteLine( "==============================================================" );
100 Console.WriteLine( "" );
101  
102 if ( (System.Object)fileName != null )
103 {
104 try
105 {
106 interp.evalFile( fileName );
107 }
108 catch ( TclException e )
109 {
110 TCL.CompletionCode code = e.getCompletionCode();
111 if ( code == TCL.CompletionCode.RETURN )
112 {
113 code = interp.updateReturnInfo();
114 if ( code != TCL.CompletionCode.OK )
115 {
116 System.Console.Error.WriteLine( "command returned bad code: " + code );
117 if ( tcl.lang.ConsoleThread.debug )
118 System.Diagnostics.Debug.WriteLine( "command returned bad code: " + code );
119 }
120 }
121 else if ( code == TCL.CompletionCode.ERROR )
122 {
123 System.Console.Error.WriteLine( interp.getResult().ToString() );
124 if ( tcl.lang.ConsoleThread.debug )
125 System.Diagnostics.Debug.WriteLine( interp.getResult().ToString() );
126 System.Diagnostics.Debug.Assert( false, interp.getResult().ToString() );
127 }
128 else if ( code != TCL.CompletionCode.EXIT )
129 {
130 System.Console.Error.WriteLine( "command returned bad code: " + code );
131 if ( tcl.lang.ConsoleThread.debug )
132 System.Diagnostics.Debug.WriteLine( "command returned bad code: " + code );
133 }
134 }
135  
136 // Note that if the above interp.evalFile() returns the main
137 // thread will exit. This may bring down the VM and stop
138 // the execution of Tcl.
139 //
140 // If the script needs to handle events, it must call
141 // vwait or do something similar.
142 //
143 // Note that the script can create AWT widgets. This will
144 // start an AWT event handling thread and keep the VM up. However,
145 // the interpreter thread (the same as the main thread) would
146 // have exited and no Tcl scripts can be executed.
147  
148 interp.dispose();
149 Sqlite3.sqlite3_shutdown();
150  
151 System.Environment.Exit( 0 );
152 }
153  
154 if ( (System.Object)fileName == null )
155 {
156 // We are running in interactive mode. Start the ConsoleThread
157 // that loops, grabbing stdin and passing it to the interp.
158  
159 ConsoleThread consoleThread = new ConsoleThread( interp );
160 consoleThread.IsBackground = true;
161 consoleThread.Start();
162  
163 // Loop forever to handle user input events in the command line.
164  
165 Notifier notifier = interp.getNotifier();
166 while ( true )
167 {
168 // process events until "exit" is called.
169  
170 notifier.doOneEvent( TCL.ALL_EVENTS );
171 }
172 }
173 }
174 }
175 #if SQLITE_TEST
176 //static void init_all(Tcl_Interp );
177 static int init_all_cmd(
178 ClientData cd,
179 Tcl_Interp interp,
180 int objc,
181 Tcl_Obj[] objv
182 )
183 {
184 Tcl_Interp slave;
185 if ( objc != 2 )
186 {
187 TCL.Tcl_WrongNumArgs( interp, 1, objv, "SLAVE" );
188 return TCL.TCL_ERROR;
189 }
190  
191 slave = TCL.Tcl_GetSlave( interp, TCL.Tcl_GetString( objv[1] ) );
192 if ( slave == null )
193 {
194 return TCL.TCL_ERROR;
195 }
196  
197 init_all( slave );
198 return TCL.TCL_OK;
199 }
200 #endif
201 // Setup SQLIte specific object for routines
202 static void init_all( Interp interp )
203 {
204 Sqlite3.Sqlite3_Init( interp );
205 Sqlite3.Sqlitetestbackup_Init( interp );
206 Sqlite3.Sqlitetestfuzzer_Init( interp );
207 Sqlite3.Sqliteconfig_Init( interp );
208 Sqlite3.Sqlitetest_autoext_Init( interp );
209 Sqlite3.Sqlitetest_func_Init( interp );
210 Sqlite3.Sqlitetest_hexio_Init( interp );
211 Sqlite3.Sqlitetest_malloc_Init( interp );
212 Sqlite3.Sqlitetest_mutex_Init( interp );
213 Sqlite3.Sqlitetestintarray_Init( interp );
214 Sqlite3.Sqlitetestschema_Init( interp );
215 Sqlite3.SqlitetestStat_Init( interp );
216 Sqlite3.Sqlitetesttclvar_Init( interp );
217 Sqlite3.Sqlitetestwholenumber_Init( interp );
218 Sqlite3.Sqlitetest1_Init( interp );
219 Sqlite3.Sqlitetest2_Init( interp );
220 Sqlite3.Sqlitetest3_Init( interp );
221 Sqlite3.Sqlitetest8_Init( interp );
222 Sqlite3.Sqlitetest9_Init( interp );
223 Sqlite3.Md5_Init( interp );
224 }
225  
226 }
227  
228 namespace tcl.lang
229 {
230 class ConsoleThread : SupportClass.ThreadClass
231 {
232 private class AnonymousClassTclEvent : TclEvent
233 {
234 public AnonymousClassTclEvent( string command, ConsoleThread enclosingInstance )
235 {
236 InitBlock( command, enclosingInstance );
237 }
238 private void InitBlock( string command, ConsoleThread enclosingInstance )
239 {
240 this.command = command;
241 this.enclosingInstance = enclosingInstance;
242 }
243 private string command;
244 private ConsoleThread enclosingInstance;
245 public ConsoleThread Enclosing_Instance
246 {
247 get
248 {
249 return enclosingInstance;
250 }
251  
252 }
253 public override int processEvent( int flags )
254 {
255  
256 // See if the command is a complete Tcl command
257  
258 if ( Interp.commandComplete( command ) )
259 {
260 if ( tcl.lang.ConsoleThread.debug )
261 {
262 WriteLine( "line was a complete command" );
263 }
264  
265 bool eval_exception = true;
266 TclObject commandObj = TclString.newInstance( command );
267  
268 try
269 {
270 commandObj.preserve();
271 Enclosing_Instance.interp.recordAndEval( commandObj, 0 );
272 eval_exception = false;
273 }
274 catch ( TclException e )
275 {
276 if ( tcl.lang.ConsoleThread.debug )
277 {
278 WriteLine( "eval returned exceptional condition" );
279 }
280  
281 TCL.CompletionCode code = e.getCompletionCode();
282 switch ( code )
283 {
284  
285 case TCL.CompletionCode.ERROR:
286  
287 Enclosing_Instance.putLine( Enclosing_Instance.err, Enclosing_Instance.interp.getResult().ToString() );
288 break;
289  
290 case TCL.CompletionCode.BREAK:
291 Enclosing_Instance.putLine( Enclosing_Instance.err, "invoked \"break\" outside of a loop" );
292 break;
293  
294 case TCL.CompletionCode.CONTINUE:
295 Enclosing_Instance.putLine( Enclosing_Instance.err, "invoked \"continue\" outside of a loop" );
296 break;
297  
298 default:
299 Enclosing_Instance.putLine( Enclosing_Instance.err, "command returned bad code: " + code );
300 break;
301  
302 }
303 }
304 finally
305 {
306 commandObj.release();
307 }
308  
309 if ( !eval_exception )
310 {
311 if ( tcl.lang.ConsoleThread.debug )
312 {
313 WriteLine( "eval returned normally" );
314 }
315  
316  
317 string evalResult = Enclosing_Instance.interp.getResult().ToString();
318  
319 if ( tcl.lang.ConsoleThread.debug )
320 {
321 WriteLine( "eval result was \"" + evalResult + "\"" );
322 }
323  
324 if ( evalResult.Length > 0 )
325 {
326 Enclosing_Instance.putLine( Enclosing_Instance.out_Renamed, evalResult );
327 }
328 }
329  
330 // Empty out the incoming command buffer
331 Enclosing_Instance.sbuf.Length = 0;
332  
333 // See if the user set a custom shell prompt for the next command
334  
335 TclObject prompt;
336  
337 try
338 {
339 prompt = Enclosing_Instance.interp.getVar( "tcl_prompt1", TCL.VarFlag.GLOBAL_ONLY );
340 }
341 catch ( TclException e )
342 {
343 prompt = null;
344 }
345 if ( prompt != null )
346 {
347 try
348 {
349  
350 Enclosing_Instance.interp.eval( prompt.ToString(), TCL.EVAL_GLOBAL );
351 }
352 catch ( TclException e )
353 {
354 Enclosing_Instance.put( Enclosing_Instance.out_Renamed, "% " );
355 }
356 }
357 else
358 {
359 Enclosing_Instance.put( Enclosing_Instance.out_Renamed, "% " );
360 }
361  
362 return 1;
363 }
364 else
365 {
366 // Interp.commandComplete() returned false
367  
368 if ( tcl.lang.ConsoleThread.debug )
369 {
370 WriteLine( "line was not a complete command" );
371 }
372  
373 // We don't have a complete command yet. Print out a level 2
374 // prompt message and wait for further inputs.
375  
376 TclObject prompt;
377  
378 try
379 {
380 prompt = Enclosing_Instance.interp.getVar( "tcl_prompt2", TCL.VarFlag.GLOBAL_ONLY );
381 }
382 catch ( TclException )
383 {
384 prompt = null;
385 }
386 if ( prompt != null )
387 {
388 try
389 {
390  
391 Enclosing_Instance.interp.eval( prompt.ToString(), TCL.EVAL_GLOBAL );
392 }
393 catch ( TclException e )
394 {
395 Enclosing_Instance.put( Enclosing_Instance.out_Renamed, "" );
396 }
397 }
398 else
399 {
400 Enclosing_Instance.put( Enclosing_Instance.out_Renamed, "" );
401 }
402  
403 return 1;
404 }
405 } // end processEvent method
406 }
407  
408 // Interpreter associated with this console thread.
409  
410 internal Interp interp;
411  
412 // Collect the user input in this buffer until it forms a complete Tcl
413 // command.
414  
415 internal StringBuilder sbuf;
416  
417 // Used to for interactive input/output
418  
419 private Channel out_Renamed;
420 private Channel err;
421  
422 // set to true to get extra debug output
423 public static bool debug = true;
424  
425 // used to keep track of wether or not System.in.available() works
426 private static bool sysInAvailableWorks = false;
427  
428 internal ConsoleThread( Interp i )
429 {
430 Name = "ConsoleThread";
431 interp = i;
432 sbuf = new StringBuilder( 100 );
433  
434 Debugger.Break();//TODO
435 //out_Renamed = Tcl_IO.getStdChannel( StdChannel.STDOUT );
436 //err = TCL.TclIO.getStdChannel( StdChannel.STDERR );
437 }
438 override public void Run()
439 {
440 if ( debug )
441 {
442 WriteLine( "entered ConsoleThread run() method" );
443 }
444  
445  
446 put( out_Renamed, "% " );
447  
448 while ( true )
449 {
450 // Loop forever to collect user inputs in a StringBuffer.
451 // When we have a complete command, then execute it and print
452 // out the results.
453 //
454 // The loop is broken under two conditions: (1) when EOF is
455 // received inside getLine(). (2) when the "exit" command is
456 // executed in the script.
457  
458 getLine();
459 string command = sbuf.ToString();
460  
461 if ( debug )
462 {
463 WriteLine( "got line from console" );
464 WriteLine( "\"" + command + "\"" );
465 }
466  
467 // When interacting with the interpreter, one must
468 // be careful to never call a Tcl method from
469 // outside of the event loop thread. If we did
470 // something like just call interp.eval() it
471 // could crash the whole process because two
472 // threads might write over each other.
473  
474 // The only safe way to interact with Tcl is
475 // to create an event and add it to the thread
476 // safe event queue.
477  
478 AnonymousClassTclEvent Tevent = new AnonymousClassTclEvent( command, this ); // end TclEvent innerclass
479  
480 // Add the event to the thread safe event queue
481 interp.getNotifier().queueEvent( Tevent, TCL.QUEUE_TAIL );
482  
483 // Tell this thread to wait until the event has been processed.
484 Tevent.sync();
485 }
486 }
487 private static void WriteLine( string s )
488 {
489 System.Console.Out.WriteLine( s );
490 if ( debug )
491 System.Diagnostics.Debug.WriteLine( s );
492 }
493 private void getLine()
494 {
495 sbuf.Append( Console.In.ReadLine() );
496 }
497 private void putLine( Channel channel, string s )
498 // The String to print.
499 {
500 try
501 {
502 channel.write( interp, s );
503 channel.write( interp, "\n" );
504 channel.flush( interp );
505 }
506 catch ( IOException ex )
507 {
508 System.Console.Error.WriteLine( "IOException in Shell.putLine()" );
509 SupportClass.WriteStackTrace( ex, System.Console.Error );
510 }
511 catch ( TclException ex )
512 {
513 System.Console.Error.WriteLine( "TclException in Shell.putLine()" );
514 SupportClass.WriteStackTrace( ex, System.Console.Error );
515 }
516 }
517 private void put( Channel channel, string s )
518 // The String to print.
519 {
520 try
521 {
522 channel.write( interp, s );
523 channel.flush( interp );
524 }
525 catch ( IOException ex )
526 {
527 System.Console.Error.WriteLine( "IOException in Shell.put()" );
528 SupportClass.WriteStackTrace( ex, System.Console.Error );
529 }
530 catch ( TclException ex )
531 {
532 System.Console.Error.WriteLine( "TclException in Shell.put()" );
533 SupportClass.WriteStackTrace( ex, System.Console.Error );
534 }
535 }
536 static ConsoleThread()
537 {
538 {
539 try
540 {
541 // There is no way to tell whether System.in will block AWT
542 // threads, so we assume it does block if we can use
543 // System.in.available().
544  
545 long available = 0;
546 // HACK ATK
547 // available = System.Console.In.Length - System.Console.In.Position;
548 int generatedAux5 = (int)available;
549 sysInAvailableWorks = true;
550 }
551 catch ( System.Exception e )
552 {
553 // If System.in.available() causes an exception -- it's probably
554 // no supported on this platform (e.g. MS Java SDK). We assume
555 // sysInAvailableWorks is false and let the user suffer ...
556 }
557  
558 // Sun's JDK 1.2 on Windows systems is screwed up, it does not
559 // echo chars to the console unless blocking IO is used.
560 // For this reason we need to use blocking IO under Windows.
561  
562 if ( Util.Windows )
563 {
564 sysInAvailableWorks = false;
565 }
566 if ( debug )
567 {
568 WriteLine( "sysInAvailableWorks = " + sysInAvailableWorks );
569 }
570 }
571 }
572 } // end of class ConsoleThread
573 }