home *** CD-ROM | disk | FTP | other *** search
/ ftp.ee.pdx.edu / 2014.02.ftp.ee.pdx.edu.tar / ftp.ee.pdx.edu / pub / users / Harry / Blitz / OSProject / p8 / UserSystem.c < prev    next >
Text File  |  2007-09-19  |  25KB  |  715 lines

  1. code UserSystem
  2.  
  3.   -- This package contains:
  4.   --     Wrapper functions for the syscalls
  5.   --     Useful functions (e.g., StrEqual, Min, ...)
  6.   --     Printing functions (printIntVar)
  7.   --     Functions involved in HEAP allocation and freeing
  8.   --     Misc. language support routines, including error handling
  9.   --     Functions involved in THROW and CATCH processing
  10.  
  11. -----------------------------  Sys_Exit  ---------------------------------
  12.  
  13.     function Sys_Exit (returnStatus: int)
  14.       --
  15.       -- This function causes the current process and its thread to
  16.       -- terminate.  The "returnStatus" will be saved so that it can
  17.       -- be passed to a "Sys_Join" executed by the parent process.
  18.       -- This function never returns.
  19.       --
  20.         var ignore: int
  21.         ignore = DoSyscall (SYSCALL_EXIT, returnStatus, 0, 0, 0)
  22.       endFunction
  23.  
  24. -----------------------------  Sys_Shutdown  ---------------------------------
  25.  
  26.     function Sys_Shutdown ()
  27.       --
  28.       -- This function will cause an immediate shutdown of the kernel.  It
  29.       -- will not return.
  30.       --
  31.         var ignore: int
  32.         ignore = DoSyscall (SYSCALL_SHUTDOWN, 0, 0, 0, 0)
  33.       endFunction
  34.  
  35. -----------------------------  Sys_Yield  ---------------------------------
  36.  
  37.     function Sys_Yield ()
  38.       --
  39.       -- This function yields the CPU to another process on the ready list.
  40.       -- Once this process is scheduled again, this function will return.
  41.       -- From the caller's perspective, this routine is similar to a "nop".
  42.       --
  43.         var ignore: int
  44.         ignore = DoSyscall (SYSCALL_YIELD, 0, 0, 0, 0)
  45.       endFunction
  46.  
  47. -----------------------------  Sys_Fork  ---------------------------------
  48.  
  49.     function Sys_Fork () returns int
  50.       --
  51.       -- This function creates a new process which is a copy of the current
  52.       -- process.  The new process will have a copy of the virtual memory
  53.       -- space and all files open in the original process will also be open
  54.       -- in the new process.  Both processes will then return from this
  55.       -- function.  In the parent process, the pid of the child will be
  56.       -- returned; in the child, zero will be returned.
  57.       --
  58.         return DoSyscall (SYSCALL_FORK, 0, 0, 0, 0)
  59.       endFunction
  60.  
  61. -----------------------------  Sys_Join  ---------------------------------
  62.  
  63.     function Sys_Join (processID: int) returns int
  64.       --
  65.       -- This function causes the caller to wait until the process with
  66.       -- the given pid has terminated, by executing a call to "Sys_Exit".
  67.       -- The returnStatus passed by that process to "Sys_Exit" will be
  68.       -- returned from this function.  If the other process invokes
  69.       -- "Sys_Exit" first, this returnStatus will be saved until either
  70.       -- its parent executes a "Sys_Join" naming that process's pid or
  71.       -- until its parent terminates.
  72.       --
  73.         return DoSyscall (SYSCALL_JOIN, processID, 0, 0, 0)
  74.       endFunction
  75.  
  76. -----------------------------  Sys_Exec  ---------------------------------
  77.  
  78.     function Sys_Exec (filename: String) returns int
  79.       --
  80.       -- This function is passed the name of a file.  That file is assumed
  81.       -- to be an executable file.  It is read in to memory, overwriting the
  82.       -- entire address space of the current process.  Then the OS will
  83.       -- begin executing the new process.  Any open files in the current
  84.       -- process will remain open and unchanged in the new process.
  85.       -- Normally, this function will not return.  If there are problems,
  86.       -- this function will return -1.
  87.       --
  88.         return DoSyscall (SYSCALL_EXEC, filename asInteger, 0, 0, 0)
  89.       endFunction
  90.  
  91. -----------------------------  Sys_Create  ---------------------------------
  92.  
  93.     function Sys_Create (filename: String) returns int
  94.       --
  95.       -- This function creates a new file on the disk.  If all is okay,
  96.       -- it returns 0, otherwise it returns a non-zero error code.  This
  97.       -- function does not open the file; so the caller must use "Sys_Open"
  98.       -- before attempting any I/O.
  99.       --
  100.         return DoSyscall (SYSCALL_CREATE, filename asInteger, 0, 0, 0)
  101.       endFunction
  102.  
  103. -----------------------------  Sys_Open  ---------------------------------
  104.  
  105.     function Sys_Open (filename: String) returns int
  106.       --
  107.       -- This function opens a file.  The file must exist already exist.
  108.       -- If all is OK, this function returns a file descriptor, which is
  109.       -- a small, non-negative integer.  It errors occur, this function
  110.       -- returns -1.
  111.       --
  112.         return DoSyscall (SYSCALL_OPEN, filename asInteger, 0, 0, 0)
  113.       endFunction
  114.  
  115. -----------------------------  Sys_Read  ---------------------------------
  116.  
  117.     function Sys_Read (fileDesc: int, buffer: ptr to char, sizeInBytes: int) returns int
  118.       --
  119.       -- This function is passed the fileDescriptor of a file (which is
  120.       -- assumed to have been successfully opened), a pointer to an area of
  121.       -- memory, and a count of the number of bytes to transfer.  This
  122.       -- function reads that many bytes from the current position in the
  123.       -- file and places them in memory.  If there are not enough bytes
  124.       -- between the current position and the end of the file, then a lesser
  125.       -- number of bytes is transferred.  The current file position will be
  126.       -- advanced by the number of bytes transferred.
  127.       --
  128.       -- If the input is coming from the serial device (the terminal), this
  129.       -- function will wait for at least one character to be typed before
  130.       -- returning, and then will return as many characters as have been typed
  131.       -- and buffered since the previous call to this function.
  132.       --
  133.       -- This function will return the  number of characters moved.  If there
  134.       -- are errors, it will return -1.
  135.       --
  136.         return DoSyscall (SYSCALL_READ, fileDesc, buffer asInteger, sizeInBytes, 0)
  137.       endFunction
  138.  
  139. -----------------------------  Sys_Write  ---------------------------------
  140.  
  141.     function Sys_Write (fileDesc: int, buffer: ptr to char, sizeInBytes: int) returns int
  142.       --
  143.       -- This function is passed the fileDescriptor of a file (which is
  144.       -- assumed to have been successfully opened), a pointer to an area of
  145.       -- memory, and a count of the number of bytes to transfer.  This
  146.       -- function writes that many bytes from the memory to the current
  147.       -- position in the file.
  148.       --
  149.       -- If the end of the file is reached, the file's size will be increased.
  150.       --
  151.       -- The current file position will be advanced by the number of bytes
  152.       -- transferred, so that future writes will follow the data transferred in
  153.       -- this invocation.
  154.       --
  155.       -- The output may also be directed to the serial output, i.e., to the
  156.       -- terminal.
  157.       --
  158.       -- This function will return the  number of characters moved.  If there
  159.       -- are errors, it will return -1.
  160.       --
  161.         return DoSyscall (SYSCALL_WRITE, fileDesc, buffer asInteger, sizeInBytes, 0)
  162.       endFunction
  163.  
  164. -----------------------------  Sys_Seek  ---------------------------------
  165.  
  166.     function Sys_Seek (fileDesc: int, newCurrentPos: int) returns int
  167.       --
  168.       -- This function is passed the fileDescriptor of a file (which is
  169.       -- assumed to have been successfully opened), and a new current
  170.       -- position.  This function sets the current position in the file to
  171.       -- the given value and returns the new current position.
  172.       --
  173.       -- Setting the current position to zero causes the next read or write
  174.       -- to refer to the very first byte in the file.  If the file size is N
  175.       -- bytes, setting the position to N will cause the next write to append
  176.       -- data to the end of the file.
  177.       --
  178.       -- The current position is always between 0 and N, where N is the
  179.       -- file's size in bytes.
  180.       --
  181.       -- If -1 is supplied as the new current position, the current position
  182.       -- will be set to N (the file size in bytes) and N will be returned.
  183.       --
  184.       -- It is an error to supply a new current position that is less than
  185.       -- -1 or greater than N.  If so, -1 will be returned.
  186.       --
  187.         return DoSyscall (SYSCALL_SEEK, fileDesc, newCurrentPos, 0, 0)
  188.       endFunction
  189.  
  190. -----------------------------  Sys_Close  ---------------------------------
  191.  
  192.     function Sys_Close (fileDesc: int)
  193.       --
  194.       -- This function is passed the fileDescriptor of a file, which is
  195.       -- assumed to be open.  It closes the file, which includes writing
  196.       -- out any data buffered by the kernel.
  197.       --
  198.         var ignore: int
  199.         ignore = DoSyscall (SYSCALL_CLOSE, fileDesc, 0, 0, 0)
  200.       endFunction
  201.  
  202. -----------------------------  StrEqual  ---------------------------------
  203.  
  204.   function StrEqual (s1, s2: String) returns bool
  205.       --
  206.       -- Return TRUE if the strings have the same size and contain
  207.       -- the same characters
  208.       --
  209.       var i: int
  210.       if s1 arraySize != s2 arraySize
  211.         return false
  212.       endIf
  213.       for i = 0 to s1 arraySize-1
  214.         if s1[i] != s2[i]
  215.           return false
  216.         endIf
  217.       endFor
  218.       return true
  219.     endFunction
  220.  
  221. -----------------------------  StrCopy  ---------------------------------
  222.  
  223.   function StrCopy (s1, s2: String)
  224.       --
  225.       -- This function copies the characters of s2 into s1.  The sizes of
  226.       -- s1 and s2 will not change.
  227.       --
  228.       -- If the two strings are different sizes this function will copy
  229.       -- however many characters it can, i.e., it will copy
  230.       -- min(s1.size, s2.size) characters.
  231.       --
  232.       -- Note that if s1 is longer than s2, you may not get exactly what
  233.       -- you expect, since some of the  characters originally in s1
  234.       -- will remain there.
  235.       --
  236.       var i, sz: int
  237.       sz = Min (s1 arraySize, s2 arraySize)
  238.       for i = 0 to sz-1
  239.         s1[i] = s2[i]
  240.       endFor
  241.     endFunction
  242.  
  243. -----------------------------  StrCmp  ---------------------------------
  244.  
  245.   function StrCmp (s1, s2: String) returns int    -- return -1 if <, 0 if =, +1 if >
  246.       --
  247.       -- Return an integer code telling whether s1 is lexicographically
  248.       -- less-than, equal, or greater-than s2.
  249.       --     Return
  250.       --       -1 when s1 < s2
  251.       --        0 when s1 = s2
  252.       --       +1 when s1 > s2
  253.       --
  254.       var sz: int = Min (s1 arraySize, s2 arraySize)
  255.           i: int
  256.       for i = 0 to sz-1
  257.         if s1[i] < s2[i]
  258.           return -1
  259.         elseIf s1[i] > s2[i]
  260.           return 1
  261.         endIf
  262.       endFor
  263.       if s1 arraySize < s2 arraySize
  264.         return -1
  265.       elseIf s1 arraySize > s2 arraySize
  266.         return 1
  267.       else
  268.         return 0
  269.       endIf
  270.     endFunction
  271.  
  272. -----------------------------  Min  ---------------------------------
  273.  
  274.   function Min (i, j: int) returns int
  275.       if i<j
  276.         return i
  277.       else
  278.         return j
  279.       endIf
  280.     endFunction
  281.  
  282. -----------------------------  Max  ---------------------------------
  283.  
  284.   function Max (i, j: int) returns int
  285.       if i>j
  286.         return i
  287.       else
  288.         return j
  289.       endIf
  290.     endFunction
  291.  
  292. -----------------------------  printIntVar  ---------------------------------
  293.  
  294.   function printIntVar (s: String, i: int)
  295.     --
  296.     -- Helper function to making printing the value of a variable easier.
  297.     -- For example:
  298.     --       printIntVar ("myVar", myVar)
  299.     -- prints out:
  300.     --       myVar = 123
  301.     --
  302.       print (s)
  303.       print (" = ")
  304.       printInt (i)
  305.       nl () 
  306.     endFunction
  307.  
  308. -----------------------------  printHexVar  ---------------------------------
  309.  
  310.   function printHexVar (s: String, i: int)
  311.     --
  312.     -- Helper function to making printing the value of a variable easier.
  313.     -- For example:
  314.     --       printHexVar ("myVar", myVar)
  315.     -- prints out:
  316.     --       myVar = 0x0000007B
  317.     --
  318.       print (s)
  319.       print (" = ")
  320.       printHex (i)
  321.       nl () 
  322.     endFunction
  323.  
  324. -----------------------------  printBoolVar  ---------------------------------
  325.  
  326.   function printBoolVar (s: String, b: bool)
  327.     --
  328.     -- Helper function to making printing the value of a variable easier.
  329.     -- For example:
  330.     --       printBoolVar ("myVar", myVar)
  331.     -- prints out:
  332.     --       myVar = TRUE
  333.     --
  334.       print (s)
  335.       print (" = ")
  336.       printBool (b)
  337.       nl () 
  338.     endFunction
  339.  
  340. -----------------------------  printCharVar  ---------------------------------
  341.  
  342.   function printCharVar (s: String, c: char)
  343.     --
  344.     -- Helper function to making printing the value of a variable easier.
  345.     -- For example:
  346.     --       printCharVar ("myVar", myVar)
  347.     -- prints out:
  348.     --       myVar = 'q'
  349.     --
  350.       print (s)
  351.       print (" = '")
  352.       printChar (c)
  353.       print ("'\n")
  354.     endFunction
  355.  
  356. -----------------------------  printPtr  ---------------------------------
  357.  
  358.   function printPtr (s: String, p: ptr to void)
  359.     --
  360.     -- Helper function to making printing the value of a variable easier.
  361.     -- For example:
  362.     --       printPtr ("myVarAddr", &myVar)
  363.     -- prints out:
  364.     --       myVarAddr = 0x0001D9C4
  365.     --
  366.       print (s)
  367.       print (" = ")
  368.       printHex (p asInteger)
  369.       nl () 
  370.     endFunction
  371.  
  372. -----------------------------  nl  ---------------------------------
  373.  
  374.   function nl ()
  375.       printChar ('\n')
  376.     endFunction
  377.  
  378. ---------------------------  printNullTerminatedString  -------------------------------
  379.  
  380.   function printNullTerminatedString (p: ptr to char)
  381.     --
  382.     -- This function is passed a pointer to a sequence of
  383.     -- characters, followed by '\0'.  It prints them.
  384.     --
  385.     var ch: char
  386.       while true
  387.         ch = *p
  388.         if ch == '\0'
  389.           return
  390.         endIf
  391.         printChar (ch)
  392.         p = p + 1
  393.       endWhile
  394.     endFunction
  395.  
  396. -----------------------------  MemoryEqual  ---------------------------------
  397.  
  398.   function MemoryEqual (s1, s2: ptr to char, len: int) returns bool
  399.     --
  400.     -- Return TRUE if the blocks of memory contain the same bytes.
  401.     --
  402.       var i: int
  403.       for i = 0 to len-1
  404.         if *s1 != *s2
  405.           return false
  406.         endIf
  407.         s1 = s1 + 1
  408.         s2 = s2 + 1
  409.       endFor
  410.       return true
  411.     endFunction
  412.  
  413. ------------------------------------  THE HEAP  ---------------------------------
  414.  
  415.   -- The following functions (provided below) are used to implement the heap.
  416.   --    KPLSystemInitialize
  417.   --    KPLMemoryAlloc
  418.   --    KPLMemoryFree
  419.   -- The runtime system will execute calls to these routines whenever:
  420.   --    Whenever a TRY statement is executed
  421.   --    Whenever an ALLOC statement is executed
  422.   --    Whenever a FREE statement is executed
  423.   --
  424.   -- The heap implementation provided here is overly simple: Blocks of memory
  425.   -- are allocated sequentially and any attempt to "free" memory is ignored.
  426.   --
  427.   const
  428.     HEAP_SIZE = 20000
  429.   var
  430.     memoryArea: array [HEAP_SIZE] of char
  431.     nextCharToUse: int = 0
  432.     alreadyInAlloc: bool = false          -- Used to detect re-entrance
  433.  
  434. -----------------------------  KPLSystemInitialize  ---------------------------------
  435.  
  436.   function KPLSystemInitialize ()
  437.     --
  438.     -- Initialize the array count without initializing the data.
  439.     --
  440.     var p: ptr to int = (& memoryArea) asPtrTo int
  441.       *p = HEAP_SIZE
  442.     endFunction
  443.  
  444. -----------------------------  KPLMemoryAlloc  ---------------------------------
  445.  
  446.   function KPLMemoryAlloc (byteCount: int) returns ptr to char
  447.     --
  448.     -- This routine is called to allocate memory from the heap.
  449.     -- This heap implementation is trivial: It allocates space
  450.     -- sequentially, until there is no more.  When space is exhausted,
  451.     -- we throw an error.
  452.     --
  453.     -- NOTE: THIS FUNCTION IS ***NOT*** RE-ENTRANT!!!  The caller must
  454.     --       ensure that it will only be called from one thread.  (If it might
  455.     --       be called from different threads, the caller must ensure that it
  456.     --       is protected with semaphores, mutexes, etc. from being invoked
  457.     --       while it is already active!!!
  458.     --
  459.     var i: int
  460.         p: ptr to char
  461.  
  462.       -- The following test is NOT correct!!!  But it may
  463.       -- detect some cases of re-entrance...
  464.       if alreadyInAlloc
  465.         KPLSystemError ("WITHIN KPLMemoryAlloc: Reentered")
  466.       endIf
  467.       alreadyInAlloc = true
  468.  
  469.       i = nextCharToUse
  470.       if byteCount <= 0
  471.         print ("\n\nBad byteCount = ")
  472.         printInt (byteCount)
  473.         KPLSystemError ("WITHIN KPLMemoryAlloc: byte count is not positive")
  474.       endIf
  475.  
  476.       -- Add 4 bytes to the byte count, for storing a hidden byte count.
  477.       byteCount = byteCount + 4
  478.  
  479.       -- Round up to a multiple of 8.
  480.       if byteCount % 8 > 0
  481.         byteCount = (byteCount / 8 + 1) * 8
  482.       endIf
  483.  
  484.       -- Uncomment the following to see when "HEAP Alloc" occurs
  485.       /*
  486.       print ("\n+++++ KPLMemoryAlloc   byteCount: ")
  487.       printInt (byteCount)
  488.       print (", remaining: ")
  489.       printInt (HEAP_SIZE-(nextCharToUse + byteCount))
  490.       print (", returns: ")
  491.       printHex ((& (memoryArea [i])) asInteger + 4)
  492.       print (" +++++\n")
  493.       */
  494.  
  495.       nextCharToUse = nextCharToUse + byteCount
  496.       if nextCharToUse > HEAP_SIZE
  497.         KPLSystemError ("WITHIN KPLMemoryAlloc: Out of memory")
  498.       endIf
  499.       p = & (memoryArea [i])
  500.       *(p asPtrTo int) = byteCount
  501.  
  502.       alreadyInAlloc = false
  503.  
  504.       return p + 4
  505.  
  506.     endFunction
  507.  
  508. -----------------------------  KPLMemoryFree  ---------------------------------
  509.  
  510.   function KPLMemoryFree (p: ptr to char)
  511.     --
  512.     -- This routine is called to free memory in the heap.  It is passed a
  513.     -- pointer to a block of memory previously allocated in a call to "alloc".
  514.     --
  515.     -- Currently, this routine is a nop.
  516.     --
  517.       --print ("\n+++++ KPLMemoryFree called... ptr: ")
  518.       --printHex (p asInteger)
  519.       --print (" +++++\n")
  520.     endFunction
  521.  
  522. -----------------------------  KPLSystemError  ---------------------------------
  523.  
  524.   function KPLSystemError (message: String)
  525.     --
  526.     -- Come here when a fatal error occurs.  Print a message and terminate
  527.     -- the KPL program.  There will be no return from this function.
  528.     -- NOTE: This function is not aware of threads; it is better to use FatalError
  529.     -- (from the Thread package) if possible.
  530.     --
  531.       print ("\n\nFATAL KPL RUNTIME ERROR IN USER PROGRAM: ")
  532.       print (message)
  533.       nl ()
  534.       TerminateWithError ()
  535.     endFunction
  536.  
  537. ------------------------  Internal Runtime Data Structures  ------------------------
  538.   --
  539.   -- These data structures are intimately connected with the language
  540.   -- implementation and the compiler, and can safely be ignored by
  541.   -- KPL programmers.  They should not be changed without appropriate
  542.   -- modifications to the compiler.
  543.   --
  544.   type
  545.     -- The following record has a fixed format:
  546.     CATCH_RECORD = record
  547.                      next: ptr to CATCH_RECORD
  548.                      errorID: ptr to char    -- Null terminated string
  549.                      catchCodePtr: int       -- Address of the code
  550.                      oldFP: int
  551.                      oldSP: int
  552.                      fileName: ptr to char   -- Null terminated string
  553.                      lineNumber: int
  554.                    endRecord
  555.  
  556.     -- The following record has a fixed format:
  557.     DISPATCH_TABLE = record
  558.                        classDescriptor: ptr to CLASS_DESCRIPTOR
  559.                        firstMethodPtr: int    -- Address of code
  560.                      endRecord
  561.  
  562.     -- The following record has a fixed format:
  563.     CLASS_DESCRIPTOR = record
  564.                          magic: int                -- Should be 0x434C4153 == 'CLAS'
  565.                          myName: ptr to char       -- Null terminated string
  566.                          fileName: ptr to char     -- Null terminated string
  567.                          lineNumber: int
  568.                          sizeInBytes: int
  569.                          firstSuperPtr: ptr to DISPATCH_TABLE
  570.                        endRecord
  571.  
  572.     -- The following record has a fixed format:
  573.     INTERFACE_DESCRIPTOR = record
  574.                              magic: int                -- Should be 0x494E5446 == 'INTF'
  575.                              myName: ptr to char       -- Null terminated string
  576.                              fileName: ptr to char     -- Null terminated string
  577.                              lineNumber: int
  578.                              firstInterfacePtr: ptr to INTERFACE_DESCRIPTOR
  579.                            endRecord
  580.  
  581.     -- The following record has a fixed format:
  582.     OBJECT_RECORD = record
  583.                       dispatchTable: ptr to DISPATCH_TABLE
  584.                       firstField: int
  585.                     endRecord
  586.  
  587. -----------------------------  KPLIsKindOf  ---------------------------------
  588.  
  589.   function KPLIsKindOf (objPtr: ptr to Object, typeDesc: ptr to int) returns int
  590.     --
  591.     -- There will be an upcall from the runtime system to this function, which
  592.     -- will evaluate the "isKindOf" relation.  This routine determines whether
  593.     -- the object pointed to satisfies the "isKindOf" relation, i.e., whether it
  594.     -- is an instance of the given type, or of one of its super-classes or super-
  595.     -- interfaces.  It returns either 0 (for FALSE) or 1 (for TRUE).
  596.     --
  597.       var
  598.         dispTable: ptr to DISPATCH_TABLE
  599.         classDesc: ptr to CLASS_DESCRIPTOR
  600.         next: ptr to ptr to void
  601.    
  602.       -- We should never be passed a NULL pointer, but check anyway.
  603.       if objPtr == null
  604.         KPLSystemError ("WITHIN KPLIsKindOf: objPtr is NULL")
  605.       endIf
  606.  
  607.       -- If the object is uninitialized return false.
  608.       dispTable = (objPtr asPtrTo OBJECT_RECORD).dispatchTable
  609.       if dispTable == null
  610.         return 0
  611.       endIf
  612.  
  613.       classDesc = dispTable.classDescriptor
  614.  
  615.       -- Make sure the magic number is what we expect it to be.
  616.       if classDesc.magic != 0x434C4153   -- 'CLAS'
  617.         KPLSystemError ("WITHIN KPLIsKindOf: Bad Magic Number")
  618.       endIf
  619.  
  620.       -- Run through all supers.  (Each class is a super of itself.)
  621.       next = & classDesc.firstSuperPtr
  622.       while true
  623.         if *next == null
  624.           return 0
  625.         elseIf *next == typeDesc
  626.           return 1
  627.         endIf
  628.         next = next + 4
  629.       endWhile
  630.     endFunction
  631.  
  632. -----------------------------  KPLUncaughtThrow  ---------------------------------
  633.  
  634.   function KPLUncaughtThrow (errorID: ptr to char, line: int, rPtr: int)
  635.     --
  636.     -- Whenever an error is thrown but not caught, there will be an upcall from the
  637.     -- runtime system to this function.  (Exception: if "UncaughtThrowError" is thrown
  638.     -- but not caught, it will cause a fatal runtime error.)  This function will
  639.     -- print some info about the error that was thrown, then it will throw an
  640.     -- error called "UncaughtThrowError".  This error may or may not be caught by
  641.     -- the user's code.  If not, the runtime system will simply print an error and halt.
  642.     --
  643.       var
  644.         charPtr: ptr to char
  645.       print ("\n\n++++++++++ An error has been thrown but not caught ++++++++++\n")
  646.       print ("   Error Name = ")
  647.       printNullTerminatedString (errorID)
  648.       nl ()
  649.       print ("   Location at time of THROW = ")
  650.       charPtr = * (rPtr asPtrTo ptr to char)
  651.       printNullTerminatedString (charPtr)
  652.       print (":")
  653.       printInt (line)
  654.       nl ()
  655.       print ("   Currently active method or function = ")
  656.       rPtr = rPtr + 4
  657.       charPtr = * (rPtr asPtrTo ptr to char)
  658.       printNullTerminatedString (charPtr)
  659.       nl ()
  660.       printCatchStack ()
  661.       print ("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\n")
  662.       throw UncaughtThrowError (errorID, line, rPtr)
  663.     endFunction
  664.  
  665. -----------------------------  printCatchStack  ---------------------------------
  666.  
  667.   function printCatchStack ()
  668.     --
  669.     -- Print all CATCH_RECORDs on the CATCH_STACK.
  670.     --
  671.     -- NOTE: Whenever we leave the body statements in a try (i.e., fall-thru,
  672.     --       throw, or return), records from the catch stack will be popped and
  673.     --       freed.  "getCatchStack" returns a pointer to a list of CATCH_RECORDs
  674.     --       as it is when getCatchStack is called.  This routine merely reads data
  675.     --       from these records, so additional pushing and popping is okay and may
  676.     --       occur (e.g., we call "print", which may contain TRY statements).  However,
  677.     --       none of the records on the list returned by getCatchStack will be freed
  678.     --       before this routine is done looking at and printing them.
  679.     --
  680.     var p: ptr to CATCH_RECORD = getCatchStack () asPtrTo CATCH_RECORD
  681.       print ("   Here is the CATCH STACK:\n")
  682.       while p
  683.         print ("     ")
  684.         printNullTerminatedString (p.fileName)
  685.         print (":")
  686.         printInt (p. lineNumber)
  687.         print (":\t")
  688.         printNullTerminatedString (p.errorID)
  689.         --print ("\t\t(CATCH-RECORD addr = 0x")
  690.         --printHex (p asInteger)
  691.         --print (")")
  692.         nl ()
  693.         /**********
  694.         print ("     ")
  695.         printNullTerminatedString (p.errorID)
  696.         print ("\n        Source Filename:   ")
  697.         printNullTerminatedString (p.fileName)
  698.         print ("\n        Line number:       ")
  699.         printInt (p. lineNumber)
  700.         print ("\n        Catch record addr: ")
  701.         printHex (p asInteger)
  702.         print ("\n        Catch code addr:   ")
  703.         printHex (p.catchCodePtr)
  704.         print ("\n        Old FP:            ")
  705.         printHex (p.oldFP)
  706.         print ("\n        Old SP:            ")
  707.         printHex (p.oldSP)
  708.         nl ()
  709.         **********/
  710.         p = p.next
  711.       endWhile
  712.     endFunction
  713.  
  714. endCode
  715.