wasCSharpSQLite – Blame information for rev

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /*
2 * InfoCmd.java
3 *
4 * Copyright (c) 1997 Cornell University.
5 * Copyright (c) 1997 Sun Microsystems, Inc.
6 *
7 * See the file "license.terms" for information on usage and
8 * redistribution of this file, and for a DISCLAIMER OF ALL
9 * WARRANTIES.
10 *
11 * Included in SQLite3 port to C# for use in testharness only; 2008 Noah B Hart
12 *
13 * RCS @(#) $Id: InfoCmd.java,v 1.8 2001/11/16 23:57:13 mdejong Exp $
14 *
15 */
16 using System;
17 using System.Collections;
18  
19 namespace tcl.lang
20 {
21  
22 /// <summary> This class implements the built-in "info" command in Tcl.</summary>
23  
24 class InfoCmd : Command
25 {
26 private static readonly string[] validCmds = new string[] { "args", "body", "cmdcount", "commands", "complete", "default", "exists", "globals", "hostname", "level", "library", "loaded", "locals", "nameofexecutable", "patchlevel", "procs", "script", "sharedlibextension", "tclversion", "vars" };
27  
28 internal const int OPT_ARGS = 0;
29 internal const int OPT_BODY = 1;
30 internal const int OPT_CMDCOUNT = 2;
31 internal const int OPT_COMMANDS = 3;
32 internal const int OPT_COMPLETE = 4;
33 internal const int OPT_DEFAULT = 5;
34 internal const int OPT_EXISTS = 6;
35 internal const int OPT_GLOBALS = 7;
36 internal const int OPT_HOSTNAME = 8;
37 internal const int OPT_LEVEL = 9;
38 internal const int OPT_LIBRARY = 10;
39 internal const int OPT_LOADED = 11;
40 internal const int OPT_LOCALS = 12;
41 internal const int OPT_NAMEOFEXECUTABLE = 13;
42 internal const int OPT_PATCHLEVEL = 14;
43 internal const int OPT_PROCS = 15;
44 internal const int OPT_SCRIPT = 16;
45 internal const int OPT_SHAREDLIBEXTENSION = 17;
46 internal const int OPT_TCLVERSION = 18;
47 internal const int OPT_VARS = 19;
48  
49 /// <summary> Tcl_InfoObjCmd -> InfoCmd.cmdProc
50 ///
51 /// This procedure is invoked to process the "info" Tcl command.
52 /// See the user documentation for details on what it does.
53 ///
54 /// </summary>
55 /// <param name="interp">the current interpreter.
56 /// </param>
57 /// <param name="argv">command arguments.
58 /// </param>
59 /// <exception cref=""> TclException if wrong # of args or invalid argument(s).
60 /// </exception>
61 public TCL.CompletionCode cmdProc( Interp interp, TclObject[] objv )
62 {
63 int index;
64  
65 if ( objv.Length < 2 )
66 {
67 throw new TclNumArgsException( interp, 1, objv, "option ?arg arg ...?" );
68 }
69 index = TclIndex.get( interp, objv[1], validCmds, "option", 0 );
70  
71 switch ( index )
72 {
73  
74 case OPT_ARGS:
75 InfoArgsCmd( interp, objv );
76 break;
77  
78 case OPT_BODY:
79 InfoBodyCmd( interp, objv );
80 break;
81  
82 case OPT_CMDCOUNT:
83 InfoCmdCountCmd( interp, objv );
84 break;
85  
86 case OPT_COMMANDS:
87 InfoCommandsCmd( interp, objv );
88 break;
89  
90 case OPT_COMPLETE:
91 InfoCompleteCmd( interp, objv );
92 break;
93  
94 case OPT_DEFAULT:
95 InfoDefaultCmd( interp, objv );
96 break;
97  
98 case OPT_EXISTS:
99 InfoExistsCmd( interp, objv );
100 break;
101  
102 case OPT_GLOBALS:
103 InfoGlobalsCmd( interp, objv );
104 break;
105  
106 case OPT_HOSTNAME:
107 InfoHostnameCmd( interp, objv );
108 break;
109  
110 case OPT_LEVEL:
111 InfoLevelCmd( interp, objv );
112 break;
113  
114 case OPT_LIBRARY:
115 InfoLibraryCmd( interp, objv );
116 break;
117  
118 case OPT_LOADED:
119 InfoLoadedCmd( interp, objv );
120 break;
121  
122 case OPT_LOCALS:
123 InfoLocalsCmd( interp, objv );
124 break;
125  
126 case OPT_NAMEOFEXECUTABLE:
127 InfoNameOfExecutableCmd( interp, objv );
128 break;
129  
130 case OPT_PATCHLEVEL:
131 InfoPatchLevelCmd( interp, objv );
132 break;
133  
134 case OPT_PROCS:
135 InfoProcsCmd( interp, objv );
136 break;
137  
138 case OPT_SCRIPT:
139 InfoScriptCmd( interp, objv );
140 break;
141  
142 case OPT_SHAREDLIBEXTENSION:
143 InfoSharedlibCmd( interp, objv );
144 break;
145  
146 case OPT_TCLVERSION:
147 InfoTclVersionCmd( interp, objv );
148 break;
149  
150 case OPT_VARS:
151 InfoVarsCmd( interp, objv );
152 break;
153 }
154 return TCL.CompletionCode.RETURN;
155 }
156  
157 /*
158 *----------------------------------------------------------------------
159 *
160 * InfoArgsCmd --
161 *
162 * Called to implement the "info args" command that returns the
163 * argument list for a procedure. Handles the following syntax:
164 *
165 * info args procName
166 *
167 * Results:
168 * Returns if successful, raises TclException otherwise.
169 *
170 * Side effects:
171 * Returns a result in the interpreter's result object.
172 *
173 *----------------------------------------------------------------------
174 */
175  
176 private static void InfoArgsCmd( Interp interp, TclObject[] objv )
177 {
178 string name;
179 Procedure proc;
180 TclObject listObj;
181  
182 if ( objv.Length != 3 )
183 {
184 throw new TclNumArgsException( interp, 2, objv, "procname" );
185 }
186  
187 name = objv[2].ToString();
188 proc = Procedure.findProc( interp, name );
189 if ( proc == null )
190 {
191 throw new TclException( interp, "\"" + name + "\" isn't a procedure" );
192 }
193  
194 // Build a return list containing the arguments.
195  
196 listObj = TclList.newInstance();
197 for ( int i = 0; i < proc.argList.Length; i++ )
198 {
199 TclObject s = TclString.newInstance( proc.argList[i][0] );
200 TclList.append( interp, listObj, s );
201 }
202 interp.setResult( listObj );
203 return;
204 }
205  
206 /*
207 *----------------------------------------------------------------------
208 *
209 * InfoBodyCmd --
210 *
211 * Called to implement the "info body" command that returns the body
212 * for a procedure. Handles the following syntax:
213 *
214 * info body procName
215 *
216 * Results:
217 * Returns if successful, raises TclException otherwise.
218 *
219 * Side effects:
220 * Returns a result in the interpreter's result object.
221 *
222 *----------------------------------------------------------------------
223 */
224  
225 private static void InfoBodyCmd( Interp interp, TclObject[] objv )
226 {
227 string name;
228 Procedure proc;
229 //TclObject body, result;
230  
231 if ( objv.Length != 3 )
232 {
233 throw new TclNumArgsException( interp, 2, objv, "procname" );
234 }
235  
236 name = objv[2].ToString();
237 proc = Procedure.findProc( interp, name );
238 if ( proc == null )
239 {
240 throw new TclException( interp, "\"" + name + "\" isn't a procedure" );
241 }
242  
243  
244 interp.setResult( proc.body.ToString() );
245 return;
246 }
247  
248 /*
249 *----------------------------------------------------------------------
250 *
251 * InfoCmdCountCmd --
252 *
253 * Called to implement the "info cmdcount" command that returns the
254 * number of commands that have been executed. Handles the following
255 * syntax:
256 *
257 * info cmdcount
258 *
259 * Results:
260 * Returns if successful, raises TclException otherwise.
261 *
262 * Side effects:
263 * Returns a result in the interpreter's result object.
264 *
265 *----------------------------------------------------------------------
266 */
267  
268 private static void InfoCmdCountCmd( Interp interp, TclObject[] objv )
269 {
270 if ( objv.Length != 2 )
271 {
272 throw new TclNumArgsException( interp, 2, objv, null );
273 }
274 interp.setResult( interp.cmdCount );
275 return;
276 }
277  
278 /*
279 *----------------------------------------------------------------------
280 *
281 * InfoCommandsCmd --
282 *
283 * Called to implement the "info commands" command that returns the
284 * list of commands in the interpreter that match an optional pattern.
285 * The pattern, if any, consists of an optional sequence of namespace
286 * names separated by "::" qualifiers, which is followed by a
287 * glob-style pattern that restricts which commands are returned.
288 * Handles the following syntax:
289 *
290 * info commands ?pattern?
291 *
292 * Results:
293 * Returns if successful, raises TclException otherwise.
294 *
295 * Side effects:
296 * Returns a result in the interpreter's result object.
297 *
298 *----------------------------------------------------------------------
299 */
300  
301 private static void InfoCommandsCmd( Interp interp, TclObject[] objv )
302 {
303 string cmdName, pattern, simplePattern;
304 IDictionaryEnumerator search;
305 NamespaceCmd.Namespace ns;
306 NamespaceCmd.Namespace globalNs = NamespaceCmd.getGlobalNamespace( interp );
307 NamespaceCmd.Namespace currNs = NamespaceCmd.getCurrentNamespace( interp );
308 TclObject list, elemObj;
309 bool specificNsInPattern = false; // Init. to avoid compiler warning.
310 WrappedCommand cmd;
311  
312 // Get the pattern and find the "effective namespace" in which to
313 // list commands.
314  
315 if ( objv.Length == 2 )
316 {
317 simplePattern = null;
318 ns = currNs;
319 specificNsInPattern = false;
320 }
321 else if ( objv.Length == 3 )
322 {
323 // From the pattern, get the effective namespace and the simple
324 // pattern (no namespace qualifiers or ::'s) at the end. If an
325 // error was found while parsing the pattern, return it. Otherwise,
326 // if the namespace wasn't found, just leave ns NULL: we will
327 // return an empty list since no commands there can be found.
328  
329  
330 pattern = objv[2].ToString();
331  
332 // Java does not support passing an address so we pass
333 // an array of size 1 and then assign arr[0] to the value
334 NamespaceCmd.Namespace[] nsArr = new NamespaceCmd.Namespace[1];
335 NamespaceCmd.Namespace[] dummy1Arr = new NamespaceCmd.Namespace[1];
336 NamespaceCmd.Namespace[] dummy2Arr = new NamespaceCmd.Namespace[1];
337 string[] simplePatternArr = new string[1];
338  
339 NamespaceCmd.getNamespaceForQualName( interp, pattern, null, 0, nsArr, dummy1Arr, dummy2Arr, simplePatternArr );
340  
341 // Get the values out of the arrays!
342 ns = nsArr[0];
343 simplePattern = simplePatternArr[0];
344  
345 if ( ns != null )
346 {
347 // we successfully found the pattern's ns
348 specificNsInPattern = ( simplePattern.CompareTo( pattern ) != 0 );
349 }
350 }
351 else
352 {
353 throw new TclNumArgsException( interp, 2, objv, "?pattern?" );
354 }
355  
356 // Scan through the effective namespace's command table and create a
357 // list with all commands that match the pattern. If a specific
358 // namespace was requested in the pattern, qualify the command names
359 // with the namespace name.
360  
361 list = TclList.newInstance();
362  
363 if ( ns != null )
364 {
365 search = ns.cmdTable.GetEnumerator();
366 while ( search.MoveNext() )
367 {
368 cmdName = ( (string)search.Key );
369 if ( ( (System.Object)simplePattern == null ) || Util.stringMatch( cmdName, simplePattern ) )
370 {
371 if ( specificNsInPattern )
372 {
373 cmd = (WrappedCommand)search.Value;
374 elemObj = TclString.newInstance( interp.getCommandFullName( cmd ) );
375 }
376 else
377 {
378 elemObj = TclString.newInstance( cmdName );
379 }
380 TclList.append( interp, list, elemObj );
381 }
382 }
383  
384 // If the effective namespace isn't the global :: namespace, and a
385 // specific namespace wasn't requested in the pattern, then add in
386 // all global :: commands that match the simple pattern. Of course,
387 // we add in only those commands that aren't hidden by a command in
388 // the effective namespace.
389  
390 if ( ( ns != globalNs ) && !specificNsInPattern )
391 {
392 search = globalNs.cmdTable.GetEnumerator();
393 while ( search.MoveNext() )
394 {
395 cmdName = ( (string)search.Key );
396 if ( ( (System.Object)simplePattern == null ) || Util.stringMatch( cmdName, simplePattern ) )
397 {
398 if ( ns.cmdTable[cmdName] == null )
399 {
400 TclList.append( interp, list, TclString.newInstance( cmdName ) );
401 }
402 }
403 }
404 }
405 }
406  
407 interp.setResult( list );
408 return;
409 }
410  
411 /*
412 *----------------------------------------------------------------------
413 *
414 * InfoCompleteCmd --
415 *
416 * Called to implement the "info complete" command that determines
417 * whether a string is a complete Tcl command. Handles the following
418 * syntax:
419 *
420 * info complete command
421 *
422 * Results:
423 * Returns if successful, raises TclException otherwise.
424 *
425 * Side effects:
426 * Returns a result in the interpreter's result object.
427 *
428 *----------------------------------------------------------------------
429 */
430  
431 private static void InfoCompleteCmd( Interp interp, TclObject[] objv )
432 {
433 if ( objv.Length != 3 )
434 {
435 throw new TclNumArgsException( interp, 2, objv, "command" );
436 }
437  
438  
439 interp.setResult( tcl.lang.Interp.commandComplete( objv[2].ToString() ) );
440 return;
441 }
442  
443 /*
444 *----------------------------------------------------------------------
445 *
446 * InfoDefaultCmd --
447 *
448 * Called to implement the "info default" command that returns the
449 * default value for a procedure argument. Handles the following
450 * syntax:
451 *
452 * info default procName arg varName
453 *
454 * Results:
455 * Returns if successful, raises TclException otherwise.
456 *
457 * Side effects:
458 * Returns a result in the interpreter's result object.
459 *
460 *----------------------------------------------------------------------
461 */
462  
463 private static void InfoDefaultCmd( Interp interp, TclObject[] objv )
464 {
465 string procName, argName, varName;
466 Procedure proc;
467 //TclObject valueObj;
468  
469 if ( objv.Length != 5 )
470 {
471 throw new TclNumArgsException( interp, 2, objv, "procname arg varname" );
472 }
473  
474  
475 procName = objv[2].ToString();
476  
477 argName = objv[3].ToString();
478 proc = Procedure.findProc( interp, procName );
479 if ( proc == null )
480 {
481 throw new TclException( interp, "\"" + procName + "\" isn't a procedure" );
482 }
483  
484 for ( int i = 0; i < proc.argList.Length; i++ )
485 {
486  
487 if ( argName.Equals( proc.argList[i][0].ToString() ) )
488 {
489  
490 varName = objv[4].ToString();
491 try
492 {
493 if ( proc.argList[i][1] != null )
494 {
495 interp.setVar( varName, proc.argList[i][1], 0 );
496 interp.setResult( 1 );
497 }
498 else
499 {
500 interp.setVar( varName, "", 0 );
501 interp.setResult( 0 );
502 }
503 }
504 catch ( TclException excp )
505 {
506 throw new TclException( interp, "couldn't store default value in variable \"" + varName + "\"" );
507 }
508 return;
509 }
510 }
511 throw new TclException( interp, "procedure \"" + procName + "\" doesn't have an argument \"" + argName + "\"" );
512 }
513  
514 /*
515 *----------------------------------------------------------------------
516 *
517 * InfoExistsCmd --
518 *
519 * Called to implement the "info exists" command that determines
520 * whether a variable exists. Handles the following syntax:
521 *
522 * info exists varName
523 *
524 * Results:
525 * Returns if successful, raises TclException otherwise.
526 *
527 * Side effects:
528 * Returns a result in the interpreter's result object.
529 *
530 *----------------------------------------------------------------------
531 */
532  
533 private static void InfoExistsCmd( Interp interp, TclObject[] objv )
534 {
535 string varName;
536 Var var = null;
537  
538 if ( objv.Length != 3 )
539 {
540 throw new TclNumArgsException( interp, 2, objv, "varName" );
541 }
542  
543  
544 varName = objv[2].ToString();
545 Var[] result = Var.lookupVar( interp, varName, null, 0, "access", false, false );
546 if ( result != null )
547 {
548 var = result[0];
549 }
550  
551 if ( ( var != null ) && !var.isVarUndefined() )
552 {
553 interp.setResult( true );
554 }
555 else
556 {
557 interp.setResult( false );
558 }
559  
560 return;
561 }
562  
563 /*
564 *----------------------------------------------------------------------
565 *
566 * InfoGlobalsCmd --
567 *
568 * Called to implement the "info globals" command that returns the list
569 * of global variables matching an optional pattern. Handles the
570 * following syntax:
571 *
572 * info globals ?pattern?*
573 *
574 * Results:
575 * Returns if successful, raises TclException otherwise.
576 *
577 * Side effects:
578 * Returns a result in the interpreter's result object.
579 *
580 *----------------------------------------------------------------------
581 */
582  
583 private static void InfoGlobalsCmd( Interp interp, TclObject[] objv )
584 {
585 string varName, pattern;
586 NamespaceCmd.Namespace globalNs = NamespaceCmd.getGlobalNamespace( interp );
587 IDictionaryEnumerator search;
588 Var var;
589 TclObject list;
590  
591 if ( objv.Length == 2 )
592 {
593 pattern = null;
594 }
595 else if ( objv.Length == 3 )
596 {
597  
598 pattern = objv[2].ToString();
599 }
600 else
601 {
602 throw new TclNumArgsException( interp, 2, objv, "?pattern?" );
603 }
604  
605 // Scan through the global :: namespace's variable table and create a
606 // list of all global variables that match the pattern.
607  
608 list = TclList.newInstance();
609  
610 for ( search = globalNs.varTable.GetEnumerator(); search.MoveNext(); )
611 {
612 varName = ( (string)search.Key );
613 var = (Var)search.Value;
614 if ( var.isVarUndefined() )
615 {
616 continue;
617 }
618 if ( ( (System.Object)pattern == null ) || Util.stringMatch( varName, pattern ) )
619 {
620 TclList.append( interp, list, TclString.newInstance( varName ) );
621 }
622 }
623  
624 interp.setResult( list );
625 return;
626 }
627  
628 /*
629 *----------------------------------------------------------------------
630 *
631 * InfoHostnameCmd --
632 *
633 * Called to implement the "info hostname" command that returns the
634 * host name. Handles the following syntax:
635 *
636 * info hostname
637 *
638 * Results:
639 * Returns if successful, raises TclException otherwise.
640 *
641 * Side effects:
642 * Returns a result in the interpreter's result object.
643 *
644 *----------------------------------------------------------------------
645 */
646  
647 private static void InfoHostnameCmd( Interp interp, TclObject[] objv )
648 {
649 string name;
650  
651 if ( objv.Length != 2 )
652 {
653 throw new TclNumArgsException( interp, 2, objv, null );
654 }
655  
656 // FIXME : how can we find the hostname
657  
658 name = null;
659  
660 if ( (System.Object)name != null )
661 {
662 interp.setResult( name );
663 return;
664 }
665 else
666 {
667 interp.setResult( "unable to determine name of host" );
668 return;
669 }
670 }
671  
672 /*
673 *----------------------------------------------------------------------
674 *
675 * InfoLevelCmd --
676 *
677 * Called to implement the "info level" command that returns
678 * information about the call stack. Handles the following syntax:
679 *
680 * info level ?number?
681 *
682 * Results:
683 * Returns if successful, raises TclException otherwise.
684 *
685 * Side effects:
686 * Returns a result in the interpreter's result object.
687 *
688 *----------------------------------------------------------------------
689 */
690  
691 private static void InfoLevelCmd( Interp interp, TclObject[] objv )
692 {
693 int level;
694 CallFrame frame;
695 TclObject list;
696  
697 if ( objv.Length == 2 )
698 {
699 // just "info level"
700 if ( interp.varFrame == null )
701 {
702 interp.setResult( 0 );
703 }
704 else
705 {
706 interp.setResult( interp.varFrame.level );
707 }
708 return;
709 }
710 else if ( objv.Length == 3 )
711 {
712 level = TclInteger.get( interp, objv[2] );
713  
714 if ( level <= 0 )
715 {
716 if ( interp.varFrame == null )
717 {
718  
719 throw new TclException( interp, "bad level \"" + objv[2].ToString() + "\"" );
720 }
721  
722 level += interp.varFrame.level;
723 }
724  
725 for ( frame = interp.varFrame; frame != null; frame = frame.callerVar )
726 {
727 if ( frame.level == level )
728 {
729 break;
730 }
731 }
732 if ( ( frame == null ) || frame.objv == null )
733 {
734  
735 throw new TclException( interp, "bad level \"" + objv[2].ToString() + "\"" );
736 }
737  
738 list = TclList.newInstance();
739 for ( int i = 0; i < frame.objv.Length; i++ )
740 {
741 TclList.append( interp, list, TclString.newInstance( frame.objv[i] ) );
742 }
743 interp.setResult( list );
744 return;
745 }
746  
747 throw new TclNumArgsException( interp, 2, objv, "?number?" );
748 }
749  
750 /*
751 *----------------------------------------------------------------------
752 *
753 * InfoLibraryCmd --
754 *
755 * Called to implement the "info library" command that returns the
756 * library directory for the Tcl installation. Handles the following
757 * syntax:
758 *
759 * info library
760 *
761 * Results:
762 * Returns if successful, raises TclException otherwise.
763 *
764 * Side effects:
765 * Returns a result in the interpreter's result object.
766 *
767 *----------------------------------------------------------------------
768 */
769  
770 private static void InfoLibraryCmd( Interp interp, TclObject[] objv )
771 {
772 if ( objv.Length != 2 )
773 {
774 throw new TclNumArgsException( interp, 2, objv, null );
775 }
776 try
777 {
778 interp.setResult( interp.getVar( "tcl_library", TCL.VarFlag.GLOBAL_ONLY ) );
779 return;
780 }
781 catch ( TclException e )
782 {
783 // If the variable has not been defined
784 throw new TclException( interp, "no library has been specified for Tcl" );
785 }
786 }
787  
788 /*
789 *----------------------------------------------------------------------
790 *
791 * InfoLoadedCmd --
792 *
793 * Called to implement the "info loaded" command that returns the
794 * packages that have been loaded into an interpreter. Handles the
795 * following syntax:
796 *
797 * info loaded ?interp?
798 *
799 * Results:
800 * Returns if successful, raises TclException otherwise.
801 *
802 * Side effects:
803 * Returns a result in the interpreter's result object.
804 *
805 *----------------------------------------------------------------------
806 */
807  
808 private static void InfoLoadedCmd( Interp interp, TclObject[] objv )
809 {
810 if ( objv.Length != 2 && objv.Length != 3 )
811 {
812 throw new TclNumArgsException( interp, 2, objv, "?interp?" );
813 }
814 // FIXME : what should "info loaded" return?
815 throw new TclException( interp, "info loaded not implemented" );
816 }
817  
818 /*
819 *----------------------------------------------------------------------
820 *
821 * InfoLocalsCmd --
822 *
823 * Called to implement the "info locals" command to return a list of
824 * local variables that match an optional pattern. Handles the
825 * following syntax:
826 *
827 * info locals ?pattern?
828 *
829 * Results:
830 * Returns if successful, raises TclException otherwise.
831 *
832 * Side effects:
833 * Returns a result in the interpreter's result object.
834 *
835 *----------------------------------------------------------------------
836 */
837  
838 private static void InfoLocalsCmd( Interp interp, TclObject[] objv )
839 {
840 string pattern;
841 TclObject list;
842  
843 if ( objv.Length == 2 )
844 {
845 pattern = null;
846 }
847 else if ( objv.Length == 3 )
848 {
849  
850 pattern = objv[2].ToString();
851 }
852 else
853 {
854 throw new TclNumArgsException( interp, 2, objv, "?pattern?" );
855 }
856  
857 if ( interp.varFrame == null || !interp.varFrame.isProcCallFrame )
858 {
859 return;
860 }
861  
862 // Return a list containing names of first the compiled locals (i.e. the
863 // ones stored in the call frame), then the variables in the local hash
864 // table (if one exists).
865  
866 list = TclList.newInstance();
867 AppendLocals( interp, list, pattern, false );
868 interp.setResult( list );
869 return;
870 }
871  
872 /*
873 *----------------------------------------------------------------------
874 *
875 * AppendLocals --
876 *
877 * Append the local variables for the current frame to the
878 * specified list object.
879 *
880 * Results:
881 * None.
882 *
883 * Side effects:
884 * None.
885 *
886 *----------------------------------------------------------------------
887 */
888  
889 private static void AppendLocals( Interp interp, TclObject list, string pattern, bool includeLinks )
890 {
891 Var var;
892 string varName;
893 Hashtable localVarTable;
894 IDictionaryEnumerator search;
895  
896 localVarTable = interp.varFrame.varTable;
897  
898 // Compiled locals do not exist in Jacl
899  
900 if ( localVarTable != null )
901 {
902 for ( search = localVarTable.GetEnumerator(); search.MoveNext(); )
903 {
904 var = (Var)search.Value;
905 varName = (string)search.Key;
906 if ( !var.isVarUndefined() && ( includeLinks || !var.isVarLink() ) )
907 {
908 if ( ( (System.Object)pattern == null ) || Util.stringMatch( varName, pattern ) )
909 {
910 TclList.append( interp, list, TclString.newInstance( varName ) );
911 }
912 }
913 }
914 }
915 }
916  
917 /*
918 *----------------------------------------------------------------------
919 *
920 * InfoNameOfExecutableCmd --
921 *
922 * Called to implement the "info nameofexecutable" command that returns
923 * the name of the binary file running this application. Handles the
924 * following syntax:
925 *
926 * info nameofexecutable
927 *
928 * Results:
929 * Returns if successful, raises TclException otherwise.
930 *
931 * Side effects:
932 * Returns a result in the interpreter's result object.
933 *
934 *----------------------------------------------------------------------
935 */
936  
937 private static void InfoNameOfExecutableCmd( Interp interp, TclObject[] objv )
938 {
939  
940 if ( objv.Length != 2 )
941 {
942 throw new TclNumArgsException( interp, 2, objv, null );
943 }
944  
945 // We depend on a user defined property named "JAVA" since
946 // the JDK provides no means to learn the name of the executable
947 // that launched the application.
948  
949 string nameOfExecutable = "nacl";
950  
951 if ( (System.Object)nameOfExecutable != null )
952 {
953 TclObject result = TclList.newInstance();
954 TclList.append( interp, result, TclString.newInstance( nameOfExecutable ) );
955 TclList.append( interp, result, TclString.newInstance( "tcl.lang.Shell" ) );
956 interp.setResult( result );
957 }
958  
959 return;
960 }
961  
962 /*
963 *----------------------------------------------------------------------
964 *
965 * InfoPatchLevelCmd --
966 *
967 * Called to implement the "info patchlevel" command that returns the
968 * default value for an argument to a procedure. Handles the following
969 * syntax:
970 *
971 * info patchlevel
972 *
973 * Results:
974 * Returns if successful, raises TclException otherwise.
975 *
976 * Side effects:
977 * Returns a result in the interpreter's result object.
978 *
979 *----------------------------------------------------------------------
980 */
981  
982 private static void InfoPatchLevelCmd( Interp interp, TclObject[] objv )
983 {
984 if ( objv.Length != 2 )
985 {
986 throw new TclNumArgsException( interp, 2, objv, null );
987 }
988  
989 interp.setResult( interp.getVar( "tcl_patchLevel", TCL.VarFlag.GLOBAL_ONLY ) );
990 return;
991 }
992  
993 /*
994 *----------------------------------------------------------------------
995 *
996 * InfoProcsCmd --
997 *
998 * Called to implement the "info procs" command that returns the
999 * procedures in the current namespace that match an optional pattern.
1000 * Handles the following syntax:
1001 *
1002 * info procs ?pattern?
1003 *
1004 * Results:
1005 * Returns if successful, raises TclException otherwise.
1006 *
1007 * Side effects:
1008 * Returns a result in the interpreter's result object.
1009 *
1010 *----------------------------------------------------------------------
1011 */
1012  
1013 private static void InfoProcsCmd( Interp interp, TclObject[] objv )
1014 {
1015 string cmdName, pattern;
1016 NamespaceCmd.Namespace currNs = NamespaceCmd.getCurrentNamespace( interp );
1017 IDictionaryEnumerator search;
1018 WrappedCommand cmd, realCmd;
1019 TclObject list;
1020  
1021 if ( objv.Length == 2 )
1022 {
1023 pattern = null;
1024 }
1025 else if ( objv.Length == 3 )
1026 {
1027  
1028 pattern = objv[2].ToString();
1029 }
1030 else
1031 {
1032 throw new TclNumArgsException( interp, 2, objv, "?pattern?" );
1033 }
1034  
1035 // Scan through the current namespace's command table and return a list
1036 // of all procs that match the pattern.
1037  
1038 list = TclList.newInstance();
1039 for ( search = currNs.cmdTable.GetEnumerator(); search.MoveNext(); )
1040 {
1041 cmdName = ( (string)search.Key );
1042 cmd = (WrappedCommand)search.Value;
1043  
1044 // If the command isn't itself a proc, it still might be an
1045 // imported command that points to a "real" proc in a different
1046 // namespace.
1047  
1048 realCmd = NamespaceCmd.getOriginalCommand( cmd );
1049  
1050 if ( Procedure.isProc( cmd ) || ( ( realCmd != null ) && Procedure.isProc( realCmd ) ) )
1051 {
1052 if ( ( (System.Object)pattern == null ) || Util.stringMatch( cmdName, pattern ) )
1053 {
1054 TclList.append( interp, list, TclString.newInstance( cmdName ) );
1055 }
1056 }
1057 }
1058  
1059 interp.setResult( list );
1060 return;
1061 }
1062  
1063 /*
1064 *----------------------------------------------------------------------
1065 *
1066 * InfoScriptCmd --
1067 *
1068 * Called to implement the "info script" command that returns the
1069 * script file that is currently being evaluated. Handles the
1070 * following syntax:
1071 *
1072 * info script
1073 *
1074 * Results:
1075 * Returns if successful, raises TclException otherwise.
1076 *
1077 * Side effects:
1078 * Returns a result in the interpreter's result object.
1079 *
1080 *----------------------------------------------------------------------
1081 */
1082  
1083 private static void InfoScriptCmd( Interp interp, TclObject[] objv )
1084 {
1085 if ( objv.Length != 2 )
1086 {
1087 throw new TclNumArgsException( interp, 2, objv, null );
1088 }
1089  
1090 interp.setResult( interp.scriptFile );
1091 return;
1092 }
1093  
1094 /*
1095 *----------------------------------------------------------------------
1096 *
1097 * InfoSharedlibCmd --
1098 *
1099 * Called to implement the "info sharedlibextension" command that
1100 * returns the file extension used for shared libraries. Handles the
1101 * following syntax:
1102 *
1103 * info sharedlibextension
1104 *
1105 * Results:
1106 * Returns if successful, raises TclException otherwise.
1107 *
1108 * Side effects:
1109 * Returns a result in the interpreter's result object.
1110 *
1111 *----------------------------------------------------------------------
1112 */
1113  
1114 private static void InfoSharedlibCmd( Interp interp, TclObject[] objv )
1115 {
1116 if ( objv.Length != 2 )
1117 {
1118 throw new TclNumArgsException( interp, 2, objv, null );
1119 }
1120 interp.setResult( ".jar" );
1121 return;
1122 }
1123  
1124 /*
1125 *----------------------------------------------------------------------
1126 *
1127 * InfoTclVersionCmd --
1128 *
1129 * Called to implement the "info tclversion" command that returns the
1130 * version number for this Tcl library. Handles the following syntax:
1131 *
1132 * info tclversion
1133 *
1134 * Results:
1135 * Returns if successful, raises TclException otherwise.
1136 *
1137 * Side effects:
1138 * Returns a result in the interpreter's result object.
1139 *
1140 *----------------------------------------------------------------------
1141 */
1142  
1143 private static void InfoTclVersionCmd( Interp interp, TclObject[] objv )
1144 {
1145 if ( objv.Length != 2 )
1146 {
1147 throw new TclNumArgsException( interp, 2, objv, null );
1148 }
1149  
1150 interp.setResult( interp.getVar( "tcl_version", TCL.VarFlag.GLOBAL_ONLY ) );
1151 return;
1152 }
1153  
1154 /*
1155 *----------------------------------------------------------------------
1156 *
1157 * InfoVarsCmd --
1158 *
1159 * Called to implement the "info vars" command that returns the
1160 * list of variables in the interpreter that match an optional pattern.
1161 * The pattern, if any, consists of an optional sequence of namespace
1162 * names separated by "::" qualifiers, which is followed by a
1163 * glob-style pattern that restricts which variables are returned.
1164 * Handles the following syntax:
1165 *
1166 * info vars ?pattern?
1167 *
1168 * Results:
1169 * Returns if successful, raises TclException otherwise.
1170 *
1171 * Side effects:
1172 * Returns a result in the interpreter's result object.
1173 *
1174 *----------------------------------------------------------------------
1175 */
1176  
1177 private static void InfoVarsCmd( Interp interp, TclObject[] objv )
1178 {
1179 string varName, pattern, simplePattern;
1180 IDictionaryEnumerator search;
1181 Var var;
1182 NamespaceCmd.Namespace ns;
1183 NamespaceCmd.Namespace globalNs = NamespaceCmd.getGlobalNamespace( interp );
1184 NamespaceCmd.Namespace currNs = NamespaceCmd.getCurrentNamespace( interp );
1185 TclObject list, elemObj;
1186 bool specificNsInPattern = false; // Init. to avoid compiler warning.
1187  
1188 // Get the pattern and find the "effective namespace" in which to
1189 // list variables. We only use this effective namespace if there's
1190 // no active Tcl procedure frame.
1191  
1192 if ( objv.Length == 2 )
1193 {
1194 simplePattern = null;
1195 ns = currNs;
1196 specificNsInPattern = false;
1197 }
1198 else if ( objv.Length == 3 )
1199 {
1200 // From the pattern, get the effective namespace and the simple
1201 // pattern (no namespace qualifiers or ::'s) at the end. If an
1202 // error was found while parsing the pattern, return it. Otherwise,
1203 // if the namespace wasn't found, just leave ns = null: we will
1204 // return an empty list since no variables there can be found.
1205  
1206  
1207 pattern = objv[2].ToString();
1208  
1209 // Java does not support passing an address so we pass
1210 // an array of size 1 and then assign arr[0] to the value
1211 NamespaceCmd.Namespace[] nsArr = new NamespaceCmd.Namespace[1];
1212 NamespaceCmd.Namespace[] dummy1Arr = new NamespaceCmd.Namespace[1];
1213 NamespaceCmd.Namespace[] dummy2Arr = new NamespaceCmd.Namespace[1];
1214 string[] simplePatternArr = new string[1];
1215  
1216 NamespaceCmd.getNamespaceForQualName( interp, pattern, null, 0, nsArr, dummy1Arr, dummy2Arr, simplePatternArr );
1217  
1218 // Get the values out of the arrays!
1219 ns = nsArr[0];
1220 simplePattern = simplePatternArr[0];
1221  
1222 if ( ns != null )
1223 {
1224 // we successfully found the pattern's ns
1225 specificNsInPattern = ( simplePattern.CompareTo( pattern ) != 0 );
1226 }
1227 }
1228 else
1229 {
1230 throw new TclNumArgsException( interp, 2, objv, "?pattern?" );
1231 }
1232  
1233 // If the namespace specified in the pattern wasn't found, just return.
1234  
1235 if ( ns == null )
1236 {
1237 return;
1238 }
1239  
1240 list = TclList.newInstance();
1241  
1242 if ( ( interp.varFrame == null ) || !interp.varFrame.isProcCallFrame || specificNsInPattern )
1243 {
1244 // There is no frame pointer, the frame pointer was pushed only
1245 // to activate a namespace, or we are in a procedure call frame
1246 // but a specific namespace was specified. Create a list containing
1247 // only the variables in the effective namespace's variable table.
1248  
1249 search = ns.varTable.GetEnumerator();
1250 while ( search.MoveNext() )
1251 {
1252 varName = ( (string)search.Key );
1253 var = (Var)search.Value;
1254 if ( !var.isVarUndefined() || ( ( var.flags & VarFlags.NAMESPACE_VAR ) != 0 ) )
1255 {
1256 if ( ( (System.Object)simplePattern == null ) || Util.stringMatch( varName, simplePattern ) )
1257 {
1258 if ( specificNsInPattern )
1259 {
1260 elemObj = TclString.newInstance( Var.getVariableFullName( interp, var ) );
1261 }
1262 else
1263 {
1264 elemObj = TclString.newInstance( varName );
1265 }
1266 TclList.append( interp, list, elemObj );
1267 }
1268 }
1269 }
1270  
1271 // If the effective namespace isn't the global :: namespace, and a
1272 // specific namespace wasn't requested in the pattern (i.e., the
1273 // pattern only specifies variable names), then add in all global ::
1274 // variables that match the simple pattern. Of course, add in only
1275 // those variables that aren't hidden by a variable in the effective
1276 // namespace.
1277  
1278 if ( ( ns != globalNs ) && !specificNsInPattern )
1279 {
1280 search = globalNs.varTable.GetEnumerator();
1281 while ( search.MoveNext() )
1282 {
1283 varName = ( (string)search.Key );
1284 var = (Var)search.Value;
1285 if ( !var.isVarUndefined() || ( ( var.flags & VarFlags.NAMESPACE_VAR ) != 0 ) )
1286 {
1287 if ( ( (System.Object)simplePattern == null ) || Util.stringMatch( varName, simplePattern ) )
1288 {
1289  
1290 // Skip vars defined in current namespace
1291 if ( ns.varTable[varName] == null )
1292 {
1293 TclList.append( interp, list, TclString.newInstance( varName ) );
1294 }
1295 }
1296 }
1297 }
1298 }
1299 }
1300 else
1301 {
1302 AppendLocals( interp, list, simplePattern, true );
1303 }
1304  
1305 interp.setResult( list );
1306 return;
1307 }
1308 }
1309 }