Source Code Cross Referenced for Util.java in  » Scripting » jacl » itcl » lang » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Scripting » jacl » itcl.lang 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * ------------------------------------------------------------------------
0003:         *      PACKAGE:  [incr Tcl]
0004:         *  DESCRIPTION:  Object-Oriented Extensions to Tcl
0005:         *
0006:         *  [incr Tcl] provides object-oriented extensions to Tcl, much as
0007:         *  C++ provides object-oriented extensions to C.  It provides a means
0008:         *  of encapsulating related procedures together with their shared data
0009:         *  in a local namespace that is hidden from the outside world.  It
0010:         *  promotes code re-use through inheritance.  More than anything else,
0011:         *  it encourages better organization of Tcl applications through the
0012:         *  object-oriented paradigm, leading to code that is easier to
0013:         *  understand and maintain.
0014:         *
0015:         *  This segment provides common utility functions used throughout
0016:         *  the other [incr Tcl] source files.
0017:         *
0018:         * ========================================================================
0019:         *  AUTHOR:  Michael J. McLennan
0020:         *           Bell Labs Innovations for Lucent Technologies
0021:         *           mmclennan@lucent.com
0022:         *           http://www.tcltk.com/itcl
0023:         *
0024:         *     RCS:  $Id: Util.java,v 1.2 2005/09/12 00:00:50 mdejong Exp $
0025:         * ========================================================================
0026:         *           Copyright (c) 1993-1998  Lucent Technologies, Inc.
0027:         * ------------------------------------------------------------------------
0028:         * See the file "license.itcl" for information on usage and redistribution
0029:         * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
0030:         */
0031:
0032:        package itcl.lang;
0033:
0034:        import java.util.Hashtable;
0035:        import java.util.Stack;
0036:
0037:        import tcl.lang.*;
0038:
0039:        //  These records are used to keep track of reference-counted data
0040:        //  for Itcl_PreserveData and Itcl_ReleaseData.
0041:
0042:        class ItclPreservedData {
0043:            int usage; // number of active uses
0044:            ItclEventuallyFreed fobj; // Object to be freed eventually
0045:        }
0046:
0047:        interface ItclEventuallyFreed {
0048:            // Invoked when data is no longer being used
0049:            void eventuallyFreed();
0050:        }
0051:
0052:        //  This structure is used to take a snapshot of the interpreter
0053:        //  state in Itcl_SaveInterpState.  You can snapshot the state,
0054:        //  execute a command, and then back up to the result or the
0055:        //  error that was previously in progress.
0056:
0057:        class Itcl_InterpState {
0058:            int validate; // validation stamp
0059:            int status; // return code status
0060:            TclObject objResult; // result object
0061:            TclObject errorInfo; // contents of errorInfo variable
0062:            TclObject errorCode; // contents of errorCode variable
0063:        }
0064:
0065:        class Util {
0066:
0067:            // POOL OF LIST ELEMENTS FOR LINKED LIST
0068:
0069:            static Itcl_ListElem listPool = null;
0070:            static int listPoolLen = 0;
0071:
0072:            static Hashtable ItclPreservedList = new Hashtable();
0073:            // Mutex ItclPreservedListLock
0074:
0075:            static int VALID_LIST = 0x01face10; // magic bit pattern for validation
0076:            static int LIST_POOL_SIZE = 200; // max number of elements in listPool
0077:
0078:            static int STATE_VALID = 0x01233210; // magic bit pattern for validation
0079:
0080:            /*
0081:             * ------------------------------------------------------------------------
0082:             *  Itcl_Assert -> Util.Assert
0083:             *
0084:             *  Called to mimic an assert() statement in C. Raises a TclRuntimeError
0085:             *  if the test expression evaluates to false.
0086:             * ------------------------------------------------------------------------
0087:             */
0088:
0089:            static void Assert(boolean tExpr, // test expression
0090:                    String tExprStr) // string representing test expression
0091:            {
0092:                if (!tExpr)
0093:                    throw new TclRuntimeError("Itcl Assertion failed: \""
0094:                            + tExprStr + "\"");
0095:            }
0096:
0097:            /*
0098:             * ------------------------------------------------------------------------
0099:             *  Itcl_InitStack -> Util.InitStack
0100:             *
0101:             *  Initializes a stack structure, allocating a certain amount of memory
0102:             *  for the stack and setting the stack length to zero.
0103:             * ------------------------------------------------------------------------
0104:             */
0105:
0106:            static void InitStack(Itcl_Stack stack) // stack to be initialized
0107:            {
0108:                stack.s = new Stack();
0109:            }
0110:
0111:            /*
0112:             * ------------------------------------------------------------------------
0113:             *  Itcl_DeleteStack -> Util.DeleteStack
0114:             *
0115:             *  Destroys a stack structure, freeing any memory that may have been
0116:             *  allocated to represent it.
0117:             * ------------------------------------------------------------------------
0118:             */
0119:
0120:            static void DeleteStack(Itcl_Stack stack) // stack to be deleted
0121:            {
0122:                stack.s.clear();
0123:                stack.s = null;
0124:            }
0125:
0126:            /*
0127:             * ------------------------------------------------------------------------
0128:             *  Itcl_PushStack -> Util.PushStack
0129:             *
0130:             *  Pushes a piece of client data onto the top of the given stack.
0131:             *  If the stack is not large enough, it is automatically resized.
0132:             * ------------------------------------------------------------------------
0133:             */
0134:
0135:            static void PushStack(Object cdata, // data to be pushed onto stack
0136:                    Itcl_Stack stack) // stack
0137:            {
0138:                stack.s.push(cdata);
0139:            }
0140:
0141:            /*
0142:             * ------------------------------------------------------------------------
0143:             *  Itcl_PopStack -> Util.PopStack
0144:             *
0145:             *  Pops a bit of client data from the top of the given stack.
0146:             * ------------------------------------------------------------------------
0147:             */
0148:
0149:            static Object PopStack(Itcl_Stack stack) // stack to be manipulated
0150:            {
0151:                if (stack.s != null && !stack.s.empty()) {
0152:                    return stack.s.pop();
0153:                }
0154:                return null;
0155:            }
0156:
0157:            /*
0158:             * ------------------------------------------------------------------------
0159:             *  Itcl_PeekStack -> Util.PeekStack
0160:             *
0161:             *  Gets the current value from the top of the given stack.
0162:             * ------------------------------------------------------------------------
0163:             */
0164:
0165:            static Object PeekStack(Itcl_Stack stack) // stack to be examined
0166:            {
0167:                if (stack.s == null)
0168:                    return null;
0169:                return stack.s.peek();
0170:            }
0171:
0172:            /*
0173:             * ------------------------------------------------------------------------
0174:             *  Itcl_GetStackValue -> Util.GetStackValue
0175:             *
0176:             *  Gets a value at some index within the stack.  Index "0" is the
0177:             *  first value pushed onto the stack.
0178:             * ------------------------------------------------------------------------
0179:             */
0180:
0181:            static Object GetStackValue(Itcl_Stack stack, // stack to be examined
0182:                    int pos) // get value at this index
0183:            {
0184:                if (stack.s == null)
0185:                    return null;
0186:                return stack.s.elementAt(pos);
0187:            }
0188:
0189:            /*
0190:             * ------------------------------------------------------------------------
0191:             *  Itcl_GetStackSize -> Util.GetStackSize
0192:             *
0193:             *  Gets the number of elements in the stack.
0194:             * ------------------------------------------------------------------------
0195:             */
0196:
0197:            static int GetStackSize(Itcl_Stack stack) // stack
0198:            {
0199:                if (stack.s == null)
0200:                    return 0;
0201:                return stack.s.size();
0202:            }
0203:
0204:            /*
0205:             * ------------------------------------------------------------------------
0206:             *  Itcl_InitList -> Util.InitList
0207:             *
0208:             *  Initializes a linked list structure, setting the list to the empty
0209:             *  state.
0210:             * ------------------------------------------------------------------------
0211:             */
0212:
0213:            static void InitList(Itcl_List list) // list to be initialized
0214:            {
0215:                list.validate = Util.VALID_LIST;
0216:                list.num = 0;
0217:                list.head = null;
0218:                list.tail = null;
0219:            }
0220:
0221:            /*
0222:             * ------------------------------------------------------------------------
0223:             *  Itcl_DeleteList -> Util.DeleteList
0224:             *
0225:             *  Destroys a linked list structure, deleting all of its elements and
0226:             *  setting it to an empty state.  If the elements have memory associated
0227:             *  with them, this memory must be freed before deleting the list or it
0228:             *  will be lost.
0229:             * ------------------------------------------------------------------------
0230:             */
0231:
0232:            static void DeleteList(Itcl_List list) // list to be deleted
0233:            {
0234:                Itcl_ListElem elem;
0235:
0236:                Assert(list.validate == Util.VALID_LIST,
0237:                        "list.validate == Util.VALID_LIST");
0238:
0239:                elem = list.head;
0240:                while (elem != null) {
0241:                    elem = Util.DeleteListElem(elem);
0242:                }
0243:                list.validate = 0;
0244:            }
0245:
0246:            /*
0247:             * ------------------------------------------------------------------------
0248:             *  Itcl_CreateListElem -> Util.CreateListElem
0249:             *
0250:             *  Low-level routined used by procedures like InsertList() and
0251:             *  AppendList() to create new list elements.  If elements are
0252:             *  available, one is taken from the list element pool.  Otherwise,
0253:             *  a new one is allocated.
0254:             * ------------------------------------------------------------------------
0255:             */
0256:
0257:            static Itcl_ListElem CreateListElem(Itcl_List list) // list that will contain this new element
0258:            {
0259:                Itcl_ListElem elem;
0260:
0261:                if (listPoolLen > 0) {
0262:                    elem = listPool;
0263:                    listPool = elem.next;
0264:                    --listPoolLen;
0265:                } else {
0266:                    elem = new Itcl_ListElem();
0267:                }
0268:                elem.owner = list;
0269:                elem.value = null;
0270:                elem.next = null;
0271:                elem.prev = null;
0272:
0273:                return elem;
0274:            }
0275:
0276:            /*
0277:             * ------------------------------------------------------------------------
0278:             *  Itcl_DeleteListElem -> Util.DeleteListElem
0279:             *
0280:             *  Destroys a single element in a linked list, returning it to a pool of
0281:             *  elements that can be later reused.  Returns a pointer to the next
0282:             *  element in the list.
0283:             * ------------------------------------------------------------------------
0284:             */
0285:
0286:            static Itcl_ListElem DeleteListElem(Itcl_ListElem elem) // list element to be deleted
0287:            {
0288:                Itcl_List list;
0289:                Itcl_ListElem next;
0290:
0291:                next = elem.next;
0292:
0293:                if (elem.prev != null) {
0294:                    elem.prev.next = elem.next;
0295:                }
0296:                if (elem.next != null) {
0297:                    elem.next.prev = elem.prev;
0298:                }
0299:
0300:                list = elem.owner;
0301:                if (elem == list.head)
0302:                    list.head = elem.next;
0303:                if (elem == list.tail)
0304:                    list.tail = elem.prev;
0305:                --list.num;
0306:
0307:                if (listPoolLen < Util.LIST_POOL_SIZE) {
0308:                    elem.next = listPool;
0309:                    listPool = elem;
0310:                    ++listPoolLen;
0311:                } else {
0312:                    elem = null;
0313:                }
0314:                return next;
0315:            }
0316:
0317:            /*
0318:             * ------------------------------------------------------------------------
0319:             *  Itcl_InsertList -> Util.InsertList
0320:             *
0321:             *  Creates a new list element containing the given value and returns
0322:             *  a pointer to it.  The element is inserted at the beginning of the
0323:             *  specified list.
0324:             * ------------------------------------------------------------------------
0325:             */
0326:
0327:            static Itcl_ListElem InsertList(Itcl_List list, // list being modified
0328:                    Object val) // value associated with new element
0329:            {
0330:                Itcl_ListElem elem;
0331:                Assert(list.validate == Util.VALID_LIST,
0332:                        "list.validate == Util.VALID_LIST");
0333:
0334:                elem = Util.CreateListElem(list);
0335:
0336:                elem.value = val;
0337:                elem.next = list.head;
0338:                elem.prev = null;
0339:                if (list.head != null) {
0340:                    list.head.prev = elem;
0341:                }
0342:                list.head = elem;
0343:                if (list.tail == null) {
0344:                    list.tail = elem;
0345:                }
0346:                ++list.num;
0347:
0348:                return elem;
0349:            }
0350:
0351:            /*
0352:             * ------------------------------------------------------------------------
0353:             *  Itcl_InsertListElem -> Util.InsertListElem
0354:             *
0355:             *  Creates a new list element containing the given value and returns
0356:             *  a pointer to it.  The element is inserted in the list just before
0357:             *  the specified element.
0358:             * ------------------------------------------------------------------------
0359:             */
0360:
0361:            static Itcl_ListElem InsertListElem(Itcl_ListElem pos, // insert just before this element
0362:                    Object val) // value associated with new element
0363:            {
0364:                Itcl_List list;
0365:                Itcl_ListElem elem;
0366:
0367:                list = pos.owner;
0368:                Assert(list.validate == Util.VALID_LIST,
0369:                        "list.validate == Util.VALID_LIST");
0370:                // Next assert makes no sense as pos was already accessed above
0371:                //Assert(pos != null,
0372:                //      "pos != null");
0373:
0374:                elem = Util.CreateListElem(list);
0375:                elem.value = val;
0376:
0377:                elem.prev = pos.prev;
0378:                if (elem.prev != null) {
0379:                    elem.prev.next = elem;
0380:                }
0381:                elem.next = pos;
0382:                pos.prev = elem;
0383:
0384:                if (list.head == pos) {
0385:                    list.head = elem;
0386:                }
0387:                if (list.tail == null) {
0388:                    list.tail = elem;
0389:                }
0390:                ++list.num;
0391:
0392:                return elem;
0393:            }
0394:
0395:            /*
0396:             * ------------------------------------------------------------------------
0397:             *  Itcl_AppendList -> Util.AppendList
0398:             *
0399:             *  Creates a new list element containing the given value and returns
0400:             *  a pointer to it.  The element is appended at the end of the
0401:             *  specified list.
0402:             * ------------------------------------------------------------------------
0403:             */
0404:
0405:            static Itcl_ListElem AppendList(Itcl_List list, // list being modified
0406:                    Object val) // value associated with new element
0407:            {
0408:                Itcl_ListElem elem;
0409:                Assert(list.validate == Util.VALID_LIST,
0410:                        "list.validate == Util.VALID_LIST");
0411:
0412:                elem = Util.CreateListElem(list);
0413:
0414:                elem.value = val;
0415:                elem.prev = list.tail;
0416:                elem.next = null;
0417:                if (list.tail != null) {
0418:                    list.tail.next = elem;
0419:                }
0420:                list.tail = elem;
0421:                if (list.head == null) {
0422:                    list.head = elem;
0423:                }
0424:                ++list.num;
0425:
0426:                return elem;
0427:            }
0428:
0429:            /*
0430:             * ------------------------------------------------------------------------
0431:             *  Itcl_AppendListElem  -> Util.AppendListElem
0432:             *
0433:             *  Creates a new list element containing the given value and returns
0434:             *  a pointer to it.  The element is inserted in the list just after
0435:             *  the specified element.
0436:             * ------------------------------------------------------------------------
0437:             */
0438:
0439:            static Itcl_ListElem AppendListElem(Itcl_ListElem pos, // insert just after this element
0440:                    Object val) // value associated with new element
0441:            {
0442:                Itcl_List list;
0443:                Itcl_ListElem elem;
0444:
0445:                list = pos.owner;
0446:                Assert(list.validate == Util.VALID_LIST,
0447:                        "list.validate == Util.VALID_LIST");
0448:                // Next assert makes no sense as pos was already accessed above
0449:                //Assert(pos != null,
0450:                //      "pos != null");
0451:
0452:                elem = Util.CreateListElem(list);
0453:                elem.value = val;
0454:
0455:                elem.next = pos.next;
0456:                if (elem.next != null) {
0457:                    elem.next.prev = elem;
0458:                }
0459:                elem.prev = pos;
0460:                pos.next = elem;
0461:
0462:                if (list.tail == pos) {
0463:                    list.tail = elem;
0464:                }
0465:                if (list.head == null) {
0466:                    list.head = elem;
0467:                }
0468:                ++list.num;
0469:
0470:                return elem;
0471:            }
0472:
0473:            /*
0474:             * ------------------------------------------------------------------------
0475:             *  Itcl_SetListValue -> Util.SetListValue
0476:             *
0477:             *  Modifies the value associated with a list element.
0478:             * ------------------------------------------------------------------------
0479:             */
0480:
0481:            static void SetListValue(Itcl_ListElem elem, // list element being modified
0482:                    Object val) // new value associated with element
0483:            {
0484:                Itcl_List list = elem.owner;
0485:                Assert(list.validate == Util.VALID_LIST,
0486:                        "list.validate == Util.VALID_LIST");
0487:                Assert(elem != null, "elem != null");
0488:
0489:                elem.value = val;
0490:            }
0491:
0492:            /*
0493:             * ------------------------------------------------------------------------
0494:             *  Itcl_NextListElem -> Util.NextListElem
0495:             *
0496:             *  Returns the next list element.
0497:             * ------------------------------------------------------------------------
0498:             */
0499:
0500:            static Itcl_ListElem NextListElem(Itcl_ListElem elem) {
0501:                return elem.next;
0502:            }
0503:
0504:            /*
0505:             * ------------------------------------------------------------------------
0506:             *  Itcl_PrevListElem -> Util.PrevListElem
0507:             *
0508:             *  Returns the prev list element.
0509:             * ------------------------------------------------------------------------
0510:             */
0511:
0512:            static Itcl_ListElem PrevListElem(Itcl_ListElem elem) {
0513:                return elem.prev;
0514:            }
0515:
0516:            /*
0517:             * ------------------------------------------------------------------------
0518:             *  Itcl_FirstListElem -> Util.FirstListElem
0519:             *
0520:             *  Returns the first list element.
0521:             * ------------------------------------------------------------------------
0522:             */
0523:
0524:            static Itcl_ListElem FirstListElem(Itcl_List l) {
0525:                return l.head;
0526:            }
0527:
0528:            /*
0529:             * ------------------------------------------------------------------------
0530:             *  Itcl_LastListElem -> Util.LastListElem
0531:             *
0532:             *  Returns the last list element.
0533:             * ------------------------------------------------------------------------
0534:             */
0535:
0536:            static Itcl_ListElem LastListElem(Itcl_List l) {
0537:                return l.tail;
0538:            }
0539:
0540:            /*
0541:             * ------------------------------------------------------------------------
0542:             *  Itcl_GetListLength -> Util.GetListLength
0543:             *
0544:             *  Returns the list length.
0545:             * ------------------------------------------------------------------------
0546:             */
0547:
0548:            static int GetListLength(Itcl_List l) {
0549:                return l.num;
0550:            }
0551:
0552:            /*
0553:             * ------------------------------------------------------------------------
0554:             *  Itcl_GetListValue -> Util.GetListValue
0555:             *
0556:             *  Get the list element value.
0557:             * ------------------------------------------------------------------------
0558:             */
0559:
0560:            static Object GetListValue(Itcl_ListElem elem) {
0561:                return elem.value;
0562:            }
0563:
0564:            /*
0565:             * ========================================================================
0566:             *  REFERENCE-COUNTED DATA
0567:             *
0568:             *  The following procedures manage generic reference-counted data.
0569:             *  They are similar in spirit to the Tcl_Preserve/Tcl_Release
0570:             *  procedures defined in the Tcl/Tk core.  But these procedures use
0571:             *  a hash table instead of a linked list to maintain the references,
0572:             *  so they scale better.  Also, the Tcl procedures have a bad behavior
0573:             *  during the "exit" command.  Their exit handler shuts them down
0574:             *  when other data is still being reference-counted and cleaned up.
0575:             *
0576:             * ------------------------------------------------------------------------
0577:             *  Itcl_EventuallyFree -> Util.EventuallyFree
0578:             *
0579:             *  Registers a piece of data so that it will be freed when no longer
0580:             *  in use.  The data is registered with an initial usage count of "0".
0581:             *  Future calls to Itcl_PreserveData() increase this usage count, and
0582:             *  calls to Itcl_ReleaseData() decrease the count until it reaches
0583:             *  zero and the data is freed.
0584:             * ------------------------------------------------------------------------
0585:             */
0586:
0587:            static void EventuallyFree(ItclEventuallyFreed fobj) // Object to be freed eventually
0588:            {
0589:                // No-op since Util.PreserveData() does everything we need.
0590:                return;
0591:            }
0592:
0593:            /*
0594:             * ------------------------------------------------------------------------
0595:             *  Itcl_PreserveData -> Util.PreserveData
0596:             *
0597:             *  Increases the usage count for a piece of data that will be freed
0598:             *  later when no longer needed.  Each call to Itcl_PreserveData()
0599:             *  puts one claim on a piece of data, and subsequent calls to
0600:             *  Itcl_ReleaseData() remove those claims.  When Itcl_EventuallyFree()
0601:             *  is called, and when the usage count reaches zero, the data is
0602:             *  freed.
0603:             * ------------------------------------------------------------------------
0604:             */
0605:
0606:            static void PreserveData(ItclEventuallyFreed fobj) // data to be preserved
0607:            {
0608:                ItclPreservedData chunk;
0609:
0610:                //  If the fobj value is null, do nothing.
0611:
0612:                if (fobj == null) {
0613:                    return;
0614:                }
0615:
0616:                //  ItclPreservedList already intialized so that it
0617:                //  can be used as a monitor.
0618:
0619:                synchronized (ItclPreservedList) {
0620:
0621:                    //  Find the data in the global list and bump its usage count.
0622:
0623:                    chunk = (ItclPreservedData) ItclPreservedList.get(fobj);
0624:                    if (chunk == null) {
0625:                        chunk = new ItclPreservedData();
0626:                        chunk.fobj = fobj;
0627:                        chunk.usage = 0;
0628:                        ItclPreservedList.put(fobj, chunk);
0629:                    } else {
0630:                        // No-op
0631:                    }
0632:
0633:                    //  Only increment the usage if it is non-negative.
0634:                    //  Negative numbers mean that the data is in the process
0635:                    //  of being destroyed by Itcl_ReleaseData(), and should
0636:                    //  not be further preserved.
0637:
0638:                    if (chunk.usage >= 0) {
0639:                        chunk.usage++;
0640:                    }
0641:
0642:                } // end synchronized block
0643:            }
0644:
0645:            /*
0646:             * ------------------------------------------------------------------------
0647:             *  Itcl_ReleaseData -> Util.ReleaseData
0648:             *
0649:             *  Decreases the usage count for a piece of data that was registered
0650:             *  previously via Itcl_PreserveData().  After Itcl_EventuallyFree()
0651:             *  is called and the usage count reaches zero, the data is
0652:             *  automatically freed.
0653:             * ------------------------------------------------------------------------
0654:             */
0655:
0656:            static void ReleaseData(ItclEventuallyFreed fobj) // data to be released
0657:            {
0658:                ItclPreservedData chunk;
0659:                boolean delEntry = false;
0660:
0661:                //  If the fobj value is null, do nothing.
0662:
0663:                if (fobj == null) {
0664:                    return;
0665:                }
0666:
0667:                //  Otherwise, find the data in the global list and
0668:                //  decrement its usage count.
0669:
0670:                synchronized (ItclPreservedList) {
0671:
0672:                    chunk = (ItclPreservedData) ItclPreservedList.get(fobj);
0673:
0674:                    Assert(chunk != null, "chunk != null");
0675:
0676:                    //  Only decrement the usage if it is non-negative.
0677:                    //  When the usage reaches zero, set it to a negative number
0678:                    //  to indicate that data is being destroyed, and then
0679:                    //  invoke the client delete proc.  When the data is deleted,
0680:                    //  remove the entry from the preservation list.
0681:
0682:                    if (chunk.usage > 0 && --chunk.usage == 0) {
0683:                        chunk.usage = -1; // cannot preserve/release anymore
0684:                        delEntry = true;
0685:                    }
0686:
0687:                } // end synchronized block
0688:
0689:                if (delEntry) {
0690:                    fobj.eventuallyFreed();
0691:
0692:                    synchronized (ItclPreservedList) {
0693:                        ItclPreservedList.remove(fobj);
0694:                    } // end synchronized block
0695:                }
0696:            }
0697:
0698:            /*
0699:             * ------------------------------------------------------------------------
0700:             *  Itcl_SaveInterpState -> Util.SaveInterpState
0701:             *
0702:             *  Takes a snapshot of the current result state of the interpreter.
0703:             *  The snapshot can be restored at any point by Itcl_RestoreInterpState.
0704:             *  So if you are in the middle of building a return result, you can
0705:             *  snapshot the interpreter, execute a command that might generate an
0706:             *  error, restore the snapshot, and continue building the result string.
0707:             *
0708:             *  Once a snapshot is saved, it must be restored by calling
0709:             *  Itcl_RestoreInterpState, or discarded by calling
0710:             *  Itcl_DiscardInterpState.  Otherwise, memory will be leaked.
0711:             *
0712:             *  Returns a token representing the state of the interpreter.
0713:             * ------------------------------------------------------------------------
0714:             */
0715:
0716:            static Itcl_InterpState SaveInterpState(Interp interp, // interpreter being modified
0717:                    int status) // integer status code for current operation
0718:            {
0719:                Itcl_InterpState info;
0720:                TclObject val = null;
0721:
0722:                info = new Itcl_InterpState();
0723:                info.validate = Util.STATE_VALID;
0724:                info.status = status;
0725:                info.errorInfo = null;
0726:                info.errorCode = null;
0727:
0728:                //  Get the result object from the interpreter.  This synchronizes
0729:                //  the old-style result, so we don't have to worry about it.
0730:                //  Keeping the object result is enough.
0731:
0732:                info.objResult = interp.getResult();
0733:                info.objResult.preserve();
0734:
0735:                //  If an error is in progress, preserve its state.
0736:
0737:                try {
0738:                    val = null;
0739:                    val = interp.getVar("errorInfo", TCL.GLOBAL_ONLY);
0740:                } catch (TclException ex) {
0741:                }
0742:                if (val != null && (val.toString().length() > 0)) {
0743:                    info.errorInfo = val;
0744:                    info.errorInfo.preserve();
0745:                }
0746:
0747:                try {
0748:                    val = null;
0749:                    val = interp.getVar("errorCode", TCL.GLOBAL_ONLY);
0750:                } catch (TclException ex) {
0751:                }
0752:                if (val != null && (val.toString().length() > 0)) {
0753:                    info.errorCode = val;
0754:                    info.errorCode.preserve();
0755:                }
0756:
0757:                //  Now, reset the interpreter to a clean state.
0758:
0759:                interp.resetResult();
0760:
0761:                return info;
0762:            }
0763:
0764:            /*
0765:             * ------------------------------------------------------------------------
0766:             *  Itcl_RestoreInterpState -> Util.RestoreInterpState
0767:             *
0768:             *  Restores the state of the interpreter to a snapshot taken by
0769:             *  Itcl_SaveInterpState.  This affects variables such as "errorInfo"
0770:             *  and "errorCode".  After this call, the token for the interpreter
0771:             *  state is no longer valid.
0772:             *
0773:             *  Returns the status code that was pending at the time the state was
0774:             *  captured.
0775:             * ------------------------------------------------------------------------
0776:             */
0777:
0778:            static int RestoreInterpState(Interp interp, // interpreter being modified
0779:                    Itcl_InterpState state) // token representing interpreter state
0780:            {
0781:                Itcl_InterpState info = state;
0782:                int status;
0783:
0784:                Assert(info.validate == Util.STATE_VALID,
0785:                        "info.validate == Util.STATE_VALID");
0786:
0787:                interp.resetResult();
0788:
0789:                //  If an error is in progress, restore its state.
0790:                //  Set the error code the hard way--set the variable directly
0791:                //  and fix the interpreter flags.  Otherwise, if the error code
0792:                //  string is really a list, it will get wrapped in extra {}'s.
0793:
0794:                if (info.errorInfo != null) {
0795:                    interp.addErrorInfo(info.errorInfo.toString());
0796:                    info.errorInfo.release();
0797:                    info.errorInfo = null;
0798:                }
0799:
0800:                if (info.errorCode != null) {
0801:                    interp.setErrorCode(info.errorCode);
0802:                    info.errorCode.release();
0803:                    info.errorCode = null;
0804:                }
0805:
0806:                //  Assign the object result back to the interpreter, then
0807:                //  release our hold on it.
0808:
0809:                interp.setResult(info.objResult);
0810:                info.objResult.release();
0811:                info.objResult = null;
0812:
0813:                status = info.status;
0814:                info.validate = 0;
0815:                info = null;
0816:
0817:                return status;
0818:            }
0819:
0820:            /*
0821:             * ------------------------------------------------------------------------
0822:             *  Itcl_DiscardInterpState -> Util.DiscardInterpState
0823:             *
0824:             *  Frees the memory associated with an interpreter snapshot taken by
0825:             *  Itcl_SaveInterpState.  If the snapshot is not restored, this
0826:             *  procedure must be called to discard it, or the memory will be lost.
0827:             *  After this call, the token for the interpreter state is no longer
0828:             *  valid.
0829:             * ------------------------------------------------------------------------
0830:             */
0831:
0832:            static void DiscardInterpState(Itcl_InterpState state) // token representing interpreter state
0833:            {
0834:                Itcl_InterpState info = state;
0835:
0836:                Assert(info.validate == Util.STATE_VALID,
0837:                        "info.validate == Util.STATE_VALID");
0838:
0839:                if (info.errorInfo != null) {
0840:                    info.errorInfo.release();
0841:                    info.errorInfo = null;
0842:                }
0843:                if (info.errorCode != null) {
0844:                    info.errorCode.release();
0845:                    info.errorCode = null;
0846:                }
0847:                info.objResult.release();
0848:                info.objResult = null;
0849:
0850:                info.validate = 0;
0851:                info = null;
0852:            }
0853:
0854:            /*
0855:             * ------------------------------------------------------------------------
0856:             *  Itcl_Protection -> Util.Protection
0857:             *
0858:             *  Used to query/set the protection level used when commands/variables
0859:             *  are defined within a class.  The default protection level (when
0860:             *  no public/protected/private command is active) is ITCL_DEFAULT_PROTECT.
0861:             *  In the default case, new commands are treated as public, while new
0862:             *  variables are treated as protected.
0863:             *
0864:             *  If the specified level is 0, then this procedure returns the
0865:             *  current value without changing it.  Otherwise, it sets the current
0866:             *  value to the specified protection level, and returns the previous
0867:             *  value.
0868:             * ------------------------------------------------------------------------
0869:             */
0870:
0871:            static int Protection(Interp interp, // interpreter being queried
0872:                    int newLevel) // new protection level or 0
0873:            {
0874:                int oldVal;
0875:                ItclObjectInfo info;
0876:
0877:                //  If a new level was specified, then set the protection level.
0878:                //  In any case, return the protection level as it stands right now.
0879:
0880:                info = (ItclObjectInfo) interp
0881:                        .getAssocData(ItclInt.INTERP_DATA);
0882:
0883:                Assert(info != null, "info != null");
0884:                oldVal = info.protection;
0885:
0886:                if (newLevel != 0) {
0887:                    Assert(newLevel == Itcl.PUBLIC
0888:                            || newLevel == Itcl.PROTECTED
0889:                            || newLevel == Itcl.PRIVATE
0890:                            || newLevel == Itcl.DEFAULT_PROTECT,
0891:                            "newLevel Protection");
0892:                    info.protection = newLevel;
0893:                }
0894:                return oldVal;
0895:            }
0896:
0897:            /*
0898:             * ------------------------------------------------------------------------
0899:             *  Itcl_ProtectionStr -> Util.ProtectionStr
0900:             *
0901:             *  Converts an integer protection code (ITCL.PUBLIC, ITCL.PROTECTED,
0902:             *  or ITCL.PRIVATE) into a human-readable character string.  Returns
0903:             *  a pointer to this string.
0904:             * ------------------------------------------------------------------------
0905:             */
0906:
0907:            static String ProtectionStr(int pLevel) // protection level
0908:            {
0909:                switch (pLevel) {
0910:                case Itcl.PUBLIC:
0911:                    return "public";
0912:                case Itcl.PROTECTED:
0913:                    return "protected";
0914:                case Itcl.PRIVATE:
0915:                    return "private";
0916:                }
0917:                return "<bad-protection-code>";
0918:            }
0919:
0920:            /*
0921:             * ------------------------------------------------------------------------
0922:             *  Itcl_CanAccess -> Util.CanAccess
0923:             *
0924:             *  Checks to see if a class member can be accessed from a particular
0925:             *  namespace context.  Public things can always be accessed.  Protected
0926:             *  things can be accessed if the "from" namespace appears in the
0927:             *  inheritance hierarchy of the class namespace.  Private things
0928:             *  can be accessed only if the "from" namespace is the same as the
0929:             *  class that contains them.
0930:             *
0931:             *  Returns true/false.
0932:             * ------------------------------------------------------------------------
0933:             */
0934:
0935:            static boolean CanAccess(ItclMember member, // class member being tested
0936:                    Namespace fromNs) // namespace requesting access
0937:            {
0938:                ItclClass fromCd;
0939:                Object entry;
0940:
0941:                //  If the protection level is "public" or "private", then the
0942:                //  answer is known immediately.
0943:
0944:                if (member.protection == Itcl.PUBLIC) {
0945:                    return true;
0946:                } else if (member.protection == Itcl.PRIVATE) {
0947:                    return (member.classDefn.namesp == fromNs);
0948:                }
0949:
0950:                //  If the protection level is "protected", then check the
0951:                //  heritage of the namespace requesting access.  If cdefnPtr
0952:                //  is in the heritage, then access is allowed.
0953:
0954:                Assert(member.protection == Itcl.PROTECTED,
0955:                        "member.protection == Itcl.PROTECTED");
0956:
0957:                if (Class.IsClassNamespace(fromNs)) {
0958:                    fromCd = Class.GetClassFromNamespace(fromNs);
0959:
0960:                    entry = fromCd.heritage.get(member.classDefn);
0961:
0962:                    if (entry != null) {
0963:                        return true;
0964:                    }
0965:                }
0966:                return false;
0967:            }
0968:
0969:            /*
0970:             * ------------------------------------------------------------------------
0971:             *  Itcl_CanAccessFunc -> Util.CanAccessFunc
0972:             *
0973:             *  Checks to see if a member function with the specified protection
0974:             *  level can be accessed from a particular namespace context.  This
0975:             *  follows the same rules enforced by Itcl_CanAccess, but adds one
0976:             *  special case:  If the function is a protected method, and if the
0977:             *  current context is a base class that has the same method, then
0978:             *  access is allowed.
0979:             *
0980:             *  Returns true/false.
0981:             * ------------------------------------------------------------------------
0982:             */
0983:
0984:            static boolean CanAccessFunc(ItclMemberFunc mfunc, // member function being tested
0985:                    Namespace fromNs) // namespace requesting access
0986:            {
0987:                ItclClass cd, fromCd;
0988:                ItclMemberFunc ovlfunc;
0989:                Object entry;
0990:
0991:                //  Apply the usual rules first.
0992:
0993:                if (Util.CanAccess(mfunc.member, fromNs)) {
0994:                    return true;
0995:                }
0996:
0997:                //  As a last resort, see if the namespace is really a base
0998:                //  class of the class containing the method.  Look for a
0999:                //  method with the same name in the base class.  If there
1000:                //  is one, then this method overrides it, and the base class
1001:                //  has access.
1002:
1003:                if ((mfunc.member.flags & ItclInt.COMMON) == 0
1004:                        && Class.IsClassNamespace(fromNs)) {
1005:
1006:                    cd = mfunc.member.classDefn;
1007:                    fromCd = Class.GetClassFromNamespace(fromNs);
1008:
1009:                    if (cd.heritage.get(fromCd) != null) {
1010:                        entry = fromCd.resolveCmds.get(mfunc.member.name);
1011:
1012:                        if (entry != null) {
1013:                            ovlfunc = (ItclMemberFunc) entry;
1014:                            if ((ovlfunc.member.flags & ItclInt.COMMON) == 0
1015:                                    && ovlfunc.member.protection < Itcl.PRIVATE) {
1016:                                return true;
1017:                            }
1018:                        }
1019:                    }
1020:                }
1021:                return false;
1022:            }
1023:
1024:            /*
1025:             * ------------------------------------------------------------------------
1026:             *  Itcl_GetTrueNamespace -> Util.GetTrueNamespace
1027:             *
1028:             *  Returns the current namespace context.  This procedure is similar
1029:             *  to Tcl_GetCurrentNamespace, but it supports the notion of
1030:             *  "transparent" call frames installed by Itcl_HandleInstance.
1031:             *
1032:             *  Returns a pointer to the current namespace calling context.
1033:             * ------------------------------------------------------------------------
1034:             */
1035:
1036:            static Namespace GetTrueNamespace(Interp interp, // interpreter being queried
1037:                    ItclObjectInfo info) // object info associated with interp
1038:            {
1039:                int i;
1040:                boolean transparent;
1041:                CallFrame frame, transFrame;
1042:                Namespace contextNs;
1043:
1044:                //  See if the current call frame is on the list of transparent
1045:                //  call frames.
1046:
1047:                transparent = false;
1048:
1049:                frame = Migrate.GetCallFrame(interp, 0);
1050:                for (i = Util.GetStackSize(info.transparentFrames) - 1; i >= 0; i--) {
1051:                    transFrame = (CallFrame) Util.GetStackValue(
1052:                            info.transparentFrames, i);
1053:
1054:                    if (frame == transFrame) {
1055:                        transparent = true;
1056:                        break;
1057:                    }
1058:                }
1059:
1060:                //  If this is a transparent call frame, return the namespace
1061:                //  context one level up.
1062:
1063:                if (transparent) {
1064:                    frame = Migrate.GetCallFrame(interp, 1);
1065:                    if (frame != null) {
1066:                        contextNs = ItclAccess.getCallFrameNamespace(frame);
1067:                    } else {
1068:                        contextNs = Namespace.getGlobalNamespace(interp);
1069:                    }
1070:                } else {
1071:                    contextNs = Namespace.getCurrentNamespace(interp);
1072:                }
1073:                return contextNs;
1074:            }
1075:
1076:            /*
1077:             * ------------------------------------------------------------------------
1078:             *  Itcl_ParseNamespPath -> Util.ParseNamespPath
1079:             *
1080:             *  Parses a reference to a namespace element of the form:
1081:             *
1082:             *      namesp::namesp::namesp::element
1083:             *
1084:             *  Returns and object that contains a head and tail part.
1085:             *  head part ("namesp::namesp::namesp"), tail part ("element")
1086:             *  If the head part is missing, a the head member will be null
1087:             *  and the rest of the string is returneed as the tail.
1088:             * ------------------------------------------------------------------------
1089:             */
1090:
1091:            static ParseNamespPathResult ParseNamespPath(String name) // path name to class member
1092:            {
1093:                int i;
1094:                String head, tail;
1095:
1096:                //  Copy the name into the buffer and parse it.  Look
1097:                //  backward from the end of the string to the first '::'
1098:                //  scope qualifier.
1099:
1100:                i = name.length();
1101:
1102:                while (--i > 0) {
1103:                    if (name.charAt(i) == ':' && name.charAt(i - 1) == ':') {
1104:                        break;
1105:                    }
1106:                }
1107:
1108:                //  Found head/tail parts.  If there are extra :'s, keep backing
1109:                //  up until the head is found.  This supports the Tcl namespace
1110:                //  behavior, which allows names like "foo:::bar".
1111:
1112:                if (i > 0) {
1113:                    tail = name.substring(i + 1);
1114:
1115:                    while (i > 0 && name.charAt(i - 1) == ':') {
1116:                        i--;
1117:                    }
1118:                    head = name.substring(0, i);
1119:                }
1120:
1121:                //  No :: separators--the whole name is treated as a tail.
1122:
1123:                else {
1124:                    tail = name;
1125:                    head = null;
1126:                }
1127:
1128:                return new ParseNamespPathResult(head, tail);
1129:            }
1130:
1131:            static class ParseNamespPathResult {
1132:                String head;
1133:                String tail;
1134:
1135:                ParseNamespPathResult(String head, String tail) {
1136:                    this .head = head;
1137:                    this .tail = tail;
1138:                }
1139:            }
1140:
1141:            /*
1142:             * ------------------------------------------------------------------------
1143:             *  Itcl_DecodeScopedCommand -> Util.DecodeScopedCommand
1144:             *
1145:             *  Decodes a scoped command of the form:
1146:             *
1147:             *      namespace inscope <namesp> <command>
1148:             *
1149:             *  If the given string is not a scoped value, this procedure does
1150:             *  nothing and returns a null rNs and the passed in name
1151:             *  value as the rCmd value. If the string is a scoped value
1152:             *  then it is decoded, and the namespace, and the simple command
1153:             *  string are returned. If anything goes wrong, this procedure
1154:             *  raises a TclException.
1155:             * ------------------------------------------------------------------------
1156:             */
1157:
1158:            static DecodeScopedCommandResult DecodeScopedCommand(Interp interp, // current interpreter
1159:                    String name) // string to be decoded
1160:                    throws TclException {
1161:                Namespace ns = null;
1162:                String cmdName;
1163:                final int len = name.length();
1164:                int pos;
1165:                TclObject[] listv = null;
1166:                TclException ex = null;
1167:
1168:                cmdName = name;
1169:
1170:                if ((len > 17) && name.startsWith("namespace ")) {
1171:                    for (pos = 9; (pos < len && name.charAt(pos) == ' '); pos++) {
1172:                        // empty body: skip over spaces
1173:                    }
1174:                    if (((pos + 8) <= len)
1175:                            && (name.charAt(pos) == 'i')
1176:                            && (name.substring(pos, pos + 8).equals("inscope "))) {
1177:                        try {
1178:                            listv = TclList.getElements(interp, TclString
1179:                                    .newInstance(name));
1180:                        } catch (TclException e) {
1181:                            ex = e;
1182:                        }
1183:                        if (ex == null) {
1184:                            if (listv.length != 4) {
1185:                                // Create exception, then add error info below before throwing
1186:                                ex = new TclException(
1187:                                        interp,
1188:                                        "malformed command \""
1189:                                                + name
1190:                                                + "\": should be \""
1191:                                                + "namespace inscope namesp command\"");
1192:                            } else {
1193:                                String findNS = listv[2].toString();
1194:                                ns = Namespace.findNamespace(interp, findNS,
1195:                                        null, TCL.LEAVE_ERR_MSG);
1196:
1197:                                if (ns == null) {
1198:                                    ex = new TclException(interp, interp
1199:                                            .getResult().toString());
1200:                                } else {
1201:                                    cmdName = listv[3].toString();
1202:                                }
1203:                            }
1204:                        }
1205:
1206:                        if (ex != null) {
1207:                            String msg = "\n    (while decoding scoped command \""
1208:                                    + name + "\")";
1209:                            interp.addErrorInfo(msg);
1210:                            throw ex;
1211:                        }
1212:                    }
1213:                }
1214:
1215:                DecodeScopedCommandResult r = new DecodeScopedCommandResult();
1216:                r.rNS = ns;
1217:                r.rCmd = cmdName;
1218:                return r;
1219:            }
1220:
1221:            static class DecodeScopedCommandResult {
1222:                Namespace rNS; // returns: namespace for scoped value
1223:                String rCmd; // returns: simple command word
1224:            }
1225:
1226:            /*
1227:             * ------------------------------------------------------------------------
1228:             *  Itcl_EvalArgs -> Util.EvalArgs
1229:             *
1230:             *  This procedure invokes a list of (objc,objv) arguments as a
1231:             *  single command.  It is similar to Tcl_EvalObj, but it doesn't
1232:             *  do any parsing or compilation.  It simply treats the first
1233:             *  argument as a command and invokes that command in the current
1234:             *  context.
1235:             *
1236:             *  Returns if successful. Otherwise, this procedure raises
1237:             *  a TclException.
1238:             * ------------------------------------------------------------------------
1239:             */
1240:
1241:            static void EvalArgs(Interp interp, // current interpreter
1242:                    TclObject[] objv) // argument objects
1243:                    throws TclException {
1244:                WrappedCommand wcmd;
1245:                TclObject cmdline = null;
1246:                TclObject[] cmdlinev;
1247:
1248:                // Resolve command name to WrappedCommand
1249:
1250:                wcmd = Namespace.findCommand(interp, objv[0].toString(), null,
1251:                        0);
1252:
1253:                cmdlinev = objv;
1254:
1255:                // If the command is still not found, handle it with the
1256:                // "unknown" proc.
1257:
1258:                if (wcmd == null) {
1259:                    wcmd = Namespace.findCommand(interp, "unknown", null,
1260:                            TCL.GLOBAL_ONLY);
1261:
1262:                    if (wcmd == null) {
1263:                        interp.resetResult();
1264:                        throw new TclException(interp,
1265:                                "invalid command name \"" + objv[0].toString()
1266:                                        + "\"");
1267:                    }
1268:
1269:                    cmdline = Util.CreateArgs(interp, "unknown", objv, 0);
1270:                    cmdlinev = TclList.getElements(interp, cmdline);
1271:                }
1272:
1273:                //  Finally, invoke the command's cmdProc()
1274:
1275:                interp.resetResult();
1276:                wcmd.cmd.cmdProc(interp, cmdlinev);
1277:            }
1278:
1279:            /*
1280:             * ------------------------------------------------------------------------
1281:             *  Itcl_CreateArgs -> Util.CreateArgs
1282:             *
1283:             *  This procedure takes a string and a list of objv arguments,
1284:             *  and glues them together in a single list.  This is useful when
1285:             *  a command word needs to be prepended or substituted into a command
1286:             *  line before it is executed.  The arguments are returned in a single
1287:             *  list object, and they can be retrieved by calling
1288:             *  Tcl_ListObjGetElements.  When the arguments are no longer needed,
1289:             *  they should be discarded by decrementing the reference count for
1290:             *  the list object.
1291:             *
1292:             *  Returns a list object containing the arguments.
1293:             * ------------------------------------------------------------------------
1294:             */
1295:
1296:            static TclObject CreateArgs(Interp interp, // current interpreter
1297:                    String string, // first command word
1298:                    TclObject[] objv, // argument objects, can be null
1299:                    int skip) // number of argument objects to skip
1300:                    throws TclException {
1301:                int i;
1302:                TclObject list;
1303:
1304:                list = TclList.newInstance();
1305:                if (string != null) {
1306:                    TclList.append(interp, list, TclString.newInstance(string));
1307:                }
1308:
1309:                if (objv != null) {
1310:                    for (i = skip; i < objv.length; i++) {
1311:                        TclList.append(interp, list, objv[i]);
1312:                    }
1313:                }
1314:
1315:                list.preserve();
1316:                return list;
1317:            }
1318:
1319:            /*
1320:             * ------------------------------------------------------------------------
1321:             *  Tcl_DStringStartSublist -> Util.StartSublist
1322:             *
1323:             *  This procedure appends a open brace character to a StringBuffer.
1324:             * ------------------------------------------------------------------------
1325:             */
1326:
1327:            static void StartSublist(StringBuffer buffer) {
1328:                if (NeedSpace(buffer)) {
1329:                    buffer.append(" {");
1330:                } else {
1331:                    buffer.append('{');
1332:                }
1333:            }
1334:
1335:            /*
1336:             * ------------------------------------------------------------------------
1337:             *  Tcl_DStringEndSublist -> Util.EndSublist
1338:             *
1339:             *  This procedure appends a close brace character to a StringBuffer.
1340:             * ------------------------------------------------------------------------
1341:             */
1342:            static void EndSublist(StringBuffer buffer) {
1343:                buffer.append('}');
1344:            }
1345:
1346:            /*
1347:             * ------------------------------------------------------------------------
1348:             *  Tcl_DStringAppendElement -> Util.AppendElement
1349:             *
1350:             *  This procedure appends a list element to a StringBuffer.
1351:             * ------------------------------------------------------------------------
1352:             */
1353:
1354:            static void AppendElement(StringBuffer buffer, String elem) {
1355:                if (NeedSpace(buffer)) {
1356:                    buffer.append(' ');
1357:                }
1358:                buffer.append(elem);
1359:            }
1360:
1361:            /*
1362:             * ------------------------------------------------------------------------
1363:             *  TclNeedSpace -> Util.NeedSpace
1364:             *
1365:             *  This procedure checks to see whether it is appropriate to
1366:             *  add a space before appending a new list element to an
1367:             *  existing string.
1368:             * ------------------------------------------------------------------------
1369:             */
1370:
1371:            static boolean NeedSpace(StringBuffer buffer) {
1372:                final int len = buffer.length();
1373:
1374:                // A space is needed unless either
1375:                // (a) we're at the start of the string, or
1376:
1377:                if (len == 0) {
1378:                    return false;
1379:                }
1380:
1381:                // (b) we're at the start of a nested list-element, quoted with an
1382:                //     open curly brace; we can be nested arbitrarily deep, so long
1383:                //     as the first curly brace starts an element, so backtrack over
1384:                //     open curly braces that are trailing characters of the string; and
1385:
1386:                int end = len - 1;
1387:                while (buffer.charAt(end) == '{') {
1388:                    if (end == 0) {
1389:                        return false;
1390:                    }
1391:                    end--;
1392:                }
1393:
1394:                // (c) the trailing character of the string is already a list-element
1395:                //     separator. With the condition that the penultimate character
1396:                //     is not a backslash.
1397:
1398:                if (Character.isSpaceChar(buffer.charAt(end))
1399:                        && ((end == 0) || (buffer.charAt(end - 1) != '\\'))) {
1400:                    return false;
1401:                }
1402:
1403:                return true;
1404:            }
1405:
1406:        } // end class Util
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.