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 / p4 / System.c < prev    next >
Text File  |  2007-09-19  |  19KB  |  579 lines

  1. code System
  2.  
  3.   -- This package contains:
  4.   --     Useful functions (e.g., StrEqual, Min, ...)
  5.   --     Printing functions (e.g., printIntVar, ...)
  6.   --     Functions involved in HEAP allocation and freeing
  7.   --     Misc. language support routines, including error handling
  8.   --     Functions involved in THROW and CATCH processing
  9.  
  10. -----------------------------  MemoryEqual  ---------------------------------
  11.  
  12.   function MemoryEqual (s1, s2: ptr to char, len: int) returns bool
  13.     --
  14.     -- Return TRUE if the blocks of memory contain the same bytes.
  15.     --
  16.       var i: int
  17.       for i = 0 to len-1
  18.         if *s1 != *s2
  19.           return false
  20.         endIf
  21.         s1 = s1 + 1
  22.         s2 = s2 + 1
  23.       endFor
  24.       return true
  25.     endFunction
  26.  
  27. -----------------------------  StrEqual  ---------------------------------
  28.  
  29.   function StrEqual (s1, s2: String) returns bool
  30.       --
  31.       -- Return TRUE if the strings have the same size and contain
  32.       -- the same characters
  33.       --
  34.       var i: int
  35.       if s1 arraySize != s2 arraySize
  36.         return false
  37.       endIf
  38.       for i = 0 to s1 arraySize-1
  39.         if s1[i] != s2[i]
  40.           return false
  41.         endIf
  42.       endFor
  43.       return true
  44.     endFunction
  45.  
  46. -----------------------------  StrCopy  ---------------------------------
  47.  
  48.   function StrCopy (s1, s2: String)
  49.       --
  50.       -- This function copies the characters of s2 into s1.  The sizes of
  51.       -- s1 and s2 will not change.
  52.       --
  53.       -- If the two strings are different sizes this function will copy
  54.       -- however many characters it can, i.e., it will copy
  55.       -- min(s1.size, s2.size) characters.
  56.       --
  57.       -- Note that if s1 is longer than s2, you may not get exactly what
  58.       -- you expect, since some of the  characters originally in s1
  59.       -- will remain there.
  60.       --
  61.       var i, sz: int
  62.       sz = Min (s1 arraySize, s2 arraySize)
  63.       for i = 0 to sz-1
  64.         s1[i] = s2[i]
  65.       endFor
  66.     endFunction
  67.  
  68. -----------------------------  StrCmp  ---------------------------------
  69.  
  70.   function StrCmp (s1, s2: String) returns int    -- return -1 if <, 0 if =, +1 if >
  71.       --
  72.       -- Return an integer code telling whether s1 is lexicographically
  73.       -- less-than, equal, or greater-than s2.
  74.       --     Return
  75.       --       -1 when s1 < s2
  76.       --        0 when s1 = s2
  77.       --       +1 when s1 > s2
  78.       --
  79.       var sz: int = Min (s1 arraySize, s2 arraySize)
  80.           i: int
  81.       for i = 0 to sz-1
  82.         if s1[i] < s2[i]
  83.           return -1
  84.         elseIf s1[i] > s2[i]
  85.           return 1
  86.         endIf
  87.       endFor
  88.       if s1 arraySize < s2 arraySize
  89.         return -1
  90.       elseIf s1 arraySize > s2 arraySize
  91.         return 1
  92.       else
  93.         return 0
  94.       endIf
  95.     endFunction
  96.  
  97. -----------------------------  Min  ---------------------------------
  98.  
  99.   function Min (i, j: int) returns int
  100.       --
  101.       -- Return the smaller of the two arguments.
  102.       --
  103.       if i<j
  104.         return i
  105.       else
  106.         return j
  107.       endIf
  108.     endFunction
  109.  
  110. -----------------------------  Max  ---------------------------------
  111.  
  112.   function Max (i, j: int) returns int
  113.       --
  114.       -- Return the larger of the two arguments.
  115.       --
  116.       if i>j
  117.         return i
  118.       else
  119.         return j
  120.       endIf
  121.     endFunction
  122.  
  123. -----------------------------  printIntVar  ---------------------------------
  124.  
  125.   function printIntVar (s: String, i: int)
  126.     --
  127.     -- Helper function to making printing the value of a variable easier.
  128.     -- For example:
  129.     --       printIntVar ("myVar", myVar)
  130.     -- prints out:
  131.     --       myVar = 123
  132.     --
  133.       print (s)
  134.       print (" = ")
  135.       printInt (i)
  136.       nl () 
  137.     endFunction
  138.  
  139. -----------------------------  printHexVar  ---------------------------------
  140.  
  141.   function printHexVar (s: String, i: int)
  142.     --
  143.     -- Helper function to making printing the value of a variable easier.
  144.     -- For example:
  145.     --       printHexVar ("myVar", myVar)
  146.     -- prints out:
  147.     --       myVar = 0x0000007B
  148.     --
  149.       print (s)
  150.       print (" = ")
  151.       printHex (i)
  152.       nl () 
  153.     endFunction
  154.  
  155. -----------------------------  printBoolVar  ---------------------------------
  156.  
  157.   function printBoolVar (s: String, b: bool)
  158.     --
  159.     -- Helper function to making printing the value of a variable easier.
  160.     -- For example:
  161.     --       printBoolVar ("myVar", myVar)
  162.     -- prints out:
  163.     --       myVar = TRUE
  164.     --
  165.       print (s)
  166.       print (" = ")
  167.       printBool (b)
  168.       nl () 
  169.     endFunction
  170.  
  171. -----------------------------  printCharVar  ---------------------------------
  172.  
  173.   function printCharVar (s: String, c: char)
  174.     --
  175.     -- Helper function to making printing the value of a variable easier.
  176.     -- For example:
  177.     --       printCharVar ("myVar", myVar)
  178.     -- prints out:
  179.     --       myVar = 'q'
  180.     --
  181.       print (s)
  182.       print (" = '")
  183.       printChar (c)
  184.       print ("'\n")
  185.     endFunction
  186.  
  187. -----------------------------  printPtr  ---------------------------------
  188.  
  189.   function printPtr (s: String, p: ptr to void)
  190.     --
  191.     -- Helper function to making printing the value of a variable easier.
  192.     -- For example:
  193.     --       printPtr ("myVarAddr", &myVar)
  194.     -- prints out:
  195.     --       myVarAddr = 0x0001D9C4
  196.     --
  197.       print (s)
  198.       print (" = ")
  199.       printHex (p asInteger)
  200.       nl () 
  201.     endFunction
  202.  
  203. -----------------------------  nl  ---------------------------------
  204.  
  205.   function nl ()
  206.       printChar ('\n')
  207.     endFunction
  208.  
  209. ---------------------------  printNullTerminatedString  -------------------------------
  210.  
  211.   function printNullTerminatedString (p: ptr to char)
  212.     --
  213.     -- This function is passed a pointer to a sequence of
  214.     -- characters, followed by '\0'.  It prints them.
  215.     --
  216.     var ch: char
  217.       while true
  218.         ch = *p
  219.         if ch == '\0'
  220.           return
  221.         endIf
  222.         printChar (ch)
  223.         p = p + 1
  224.       endWhile
  225.     endFunction
  226.  
  227. -----------------------------  PrintMemory  ---------------------------------
  228.  
  229.   function PrintMemory (startingAddr, numBytes: int)
  230.     --
  231.     -- This routine dumps memory.  It is passed the starting address and the
  232.     -- number of bytes to print.
  233.     --
  234.       var i: int
  235.           charPtr: ptr to char
  236.       charPtr = ((startingAddr / 32) * 32) asPtrTo char
  237.       for i = 0 to numBytes + 31
  238.         -- Print a line every PAGE_SIZE=8K bytes
  239.         if (i % 8192 == 0)
  240.           print ("\n\n--------------------------------------------------------\n")
  241.         endIf
  242.         if (i % 32 == 0)
  243.           nl ()
  244.           printHex (charPtr asInteger)
  245.           print (":  ")
  246.         endIf
  247.        -- if (i % 8 == 0)
  248.        --   print (" ")
  249.        -- endIf
  250.         printChar (*charPtr)
  251.         charPtr = charPtr + 1
  252.       endFor
  253.       print ("\n\n--------------------------------------------------------\n")
  254.     endFunction
  255.  
  256. ------------------------------------  THE HEAP  ---------------------------------
  257.  
  258.   -- The following functions (provided below) are used to implement the heap.
  259.   --    KPLSystemInitialize
  260.   --    KPLMemoryAlloc
  261.   --    KPLMemoryFree
  262.   -- The runtime system will execute calls to these routines whenever:
  263.   --    Whenever a TRY statement is executed
  264.   --    Whenever an ALLOC statement is executed
  265.   --    Whenever a FREE statement is executed
  266.   --
  267.   -- The heap implementation provided here is overly simple: Blocks of memory
  268.   -- are allocated sequentially and any attempt to "free" memory is ignored.
  269.   --
  270.   const
  271.     HEAP_SIZE = 500000
  272.   var
  273.     memoryArea: array [HEAP_SIZE] of char
  274.     nextCharToUse: int = 0
  275.     alreadyInAlloc: bool = false          -- Used to detect re-entrance
  276.  
  277. -----------------------------  KPLSystemInitialize  ---------------------------------
  278.  
  279.   function KPLSystemInitialize ()
  280.     --
  281.     -- This routine is called directly before the "main" function is called.
  282.     --
  283.     -- Initialize the array count without initializing the data.  Here we initialize
  284.     -- a few of the bytes in the HEAP so that we can watch out for overflowing
  285.     -- into the frame region.
  286.     --
  287.     -- Also initialize the "FatalError" variable, which is a function that
  288.     -- is called whenever the program wishes to quit.
  289.     --
  290.     var p: ptr to int = (& memoryArea) asPtrTo int
  291.         p2: ptr to int
  292.       FatalError = FatalError_SimpleVersion
  293.       *p = HEAP_SIZE
  294.       for p2 = p+4 to p + 4 + HEAP_SIZE-1 by 100
  295.         *p2 = 0x48454150      -- ASCII codes for "HEAP"
  296.       endFor
  297.     endFunction
  298.  
  299. -----------------------------  FatalError1  ---------------------------------
  300.  
  301.   function FatalError_SimpleVersion (errorMessage: ptr to array of char)
  302.       print ("\nFATAL ERROR: \"")
  303.       print (errorMessage)
  304.       print ("\" -- TERMINATING!\n")
  305.       RuntimeExit ()
  306.     endFunction
  307.  
  308. -----------------------------  KPLMemoryAlloc  ---------------------------------
  309.  
  310.   function KPLMemoryAlloc (byteCount: int) returns ptr to char
  311.     --
  312.     -- This routine is called to allocate memory from the heap.
  313.     -- This heap implementation is trivial: It allocates space
  314.     -- sequentially, until there is no more.  When space is exhausted,
  315.     -- we throw an error.
  316.     --
  317.     -- NOTE: THIS FUNCTION IS ***NOT*** RE-ENTRANT!!!  The caller must
  318.     --       ensure that it will only be called from one thread.  (If it might
  319.     --       be called from different threads, the caller must ensure that it
  320.     --       is protected with semaphores, mutexes, etc. from being invoked
  321.     --       while it is already active!!!
  322.     --
  323.     var i: int
  324.         p: ptr to char
  325.  
  326.       -- The following test is NOT correct!!!  But it may
  327.       -- detect some cases of re-entrance...
  328.       if alreadyInAlloc
  329.         KPLSystemError ("WITHIN KPLMemoryAlloc: Reentered")
  330.       endIf
  331.       alreadyInAlloc = true
  332.  
  333.       i = nextCharToUse
  334.       if byteCount <= 0
  335.         print ("\n\nBad byteCount = ")
  336.         printInt (byteCount)
  337.         KPLSystemError ("WITHIN KPLMemoryAlloc: byte count is not positive")
  338.       endIf
  339.  
  340.       -- Add 4 bytes to the byte count, for storing a hidden byte count.
  341.       byteCount = byteCount + 4
  342.  
  343.       -- Round up to a multiple of 8.
  344.       if byteCount % 8 > 0
  345.         byteCount = (byteCount / 8 + 1) * 8
  346.       endIf
  347.  
  348.       -- Uncomment the following to see when "HEAP Alloc" occurs
  349.       /*
  350.       print ("\n+++++ KPLMemoryAlloc   byteCount: ")
  351.       printInt (byteCount)
  352.       print (", remaining: ")
  353.       printInt (HEAP_SIZE-(nextCharToUse + byteCount))
  354.       print (", returns: ")
  355.       printHex ((& (memoryArea [i])) asInteger + 4)
  356.       print (" +++++\n")
  357.       */
  358.  
  359.       nextCharToUse = nextCharToUse + byteCount
  360.       if nextCharToUse > HEAP_SIZE
  361.         KPLSystemError ("WITHIN KPLMemoryAlloc: Out of memory")
  362.       endIf
  363.       p = & (memoryArea [i])
  364.       *(p asPtrTo int) = byteCount
  365.  
  366.       alreadyInAlloc = false
  367.  
  368.       return p + 4
  369.  
  370.     endFunction
  371.  
  372. -----------------------------  KPLMemoryFree  ---------------------------------
  373.  
  374.   function KPLMemoryFree (p: ptr to char)
  375.     --
  376.     -- This routine is called to free memory in the heap.  It is passed a
  377.     -- pointer to a block of memory previously allocated in a call to "alloc".
  378.     --
  379.     -- Currently, this routine is a nop.
  380.     --
  381.       --print ("\n+++++ KPLMemoryFree called... ptr: ")
  382.       --printHex (p asInteger)
  383.       --print (" +++++\n")
  384.     endFunction
  385.  
  386. -----------------------------  KPLSystemError  ---------------------------------
  387.  
  388.   function KPLSystemError (message: ptr to array of char)
  389.     --
  390.     -- Come here when a fatal error occurs.  Print a message and terminate
  391.     -- the KPL program.  There will be no return from this function.
  392.     -- NOTE: This function is not aware of threads; it is better to use FatalError
  393.     -- (from the Thread package) if possible.
  394.     --
  395.       print ("\n\nFATAL KPL RUNTIME ERROR: ")
  396.       print (message)
  397.       nl ()
  398.       RuntimeExit ()
  399.     endFunction
  400.  
  401. ------------------------  Internal Runtime Data Structures  ------------------------
  402.   --
  403.   -- These data structures are intimately connected with the language
  404.   -- implementation and the compiler, and can safely be ignored by
  405.   -- KPL programmers.  They should not be changed without appropriate
  406.   -- modifications to the compiler.
  407.   --
  408.   type
  409.     -- The following record has a fixed format:
  410.     CATCH_RECORD = record
  411.                      next: ptr to CATCH_RECORD
  412.                      errorID: ptr to char    -- Null terminated string
  413.                      catchCodePtr: int       -- Address of the code
  414.                      oldFP: int
  415.                      oldSP: int
  416.                      fileName: ptr to char   -- Null terminated string
  417.                      lineNumber: int
  418.                    endRecord
  419.  
  420.     -- The following record has a fixed format:
  421.     DISPATCH_TABLE = record
  422.                        classDescriptor: ptr to CLASS_DESCRIPTOR
  423.                        firstMethodPtr: int    -- Address of code
  424.                      endRecord
  425.  
  426.     -- The following record has a fixed format:
  427.     CLASS_DESCRIPTOR = record
  428.                          magic: int                -- Should be 0x434C4153 == 'CLAS'
  429.                          myName: ptr to char       -- Null terminated string
  430.                          fileName: ptr to char     -- Null terminated string
  431.                          lineNumber: int
  432.                          sizeInBytes: int
  433.                          firstSuperPtr: ptr to DISPATCH_TABLE
  434.                        endRecord
  435.  
  436.     -- The following record has a fixed format:
  437.     INTERFACE_DESCRIPTOR = record
  438.                              magic: int                -- Should be 0x494E5446 == 'INTF'
  439.                              myName: ptr to char       -- Null terminated string
  440.                              fileName: ptr to char     -- Null terminated string
  441.                              lineNumber: int
  442.                              firstInterfacePtr: ptr to INTERFACE_DESCRIPTOR
  443.                            endRecord
  444.  
  445.     -- The following record has a fixed format:
  446.     OBJECT_RECORD = record
  447.                       dispatchTable: ptr to DISPATCH_TABLE
  448.                       firstField: int
  449.                     endRecord
  450.  
  451. -----------------------------  KPLIsKindOf  ---------------------------------
  452.  
  453.   function KPLIsKindOf (objPtr: ptr to Object, typeDesc: ptr to int) returns int
  454.     --
  455.     -- There will be an upcall from the runtime system to this function, which
  456.     -- will evaluate the "isKindOf" relation.  This routine determines whether
  457.     -- the object pointed to satisfies the "isKindOf" relation, i.e., whether it
  458.     -- is an instance of the given type, or of one of its super-classes or super-
  459.     -- interfaces.  It returns either 0 (for FALSE) or 1 (for TRUE).
  460.     --
  461.       var
  462.         dispTable: ptr to DISPATCH_TABLE
  463.         classDesc: ptr to CLASS_DESCRIPTOR
  464.         next: ptr to ptr to void
  465.    
  466.       -- We should never be passed a NULL pointer, but check anyway.
  467.       if objPtr == null
  468.         KPLSystemError ("WITHIN KPLIsKindOf: objPtr is NULL")
  469.       endIf
  470.  
  471.       -- If the object is uninitialized return false.
  472.       dispTable = (objPtr asPtrTo OBJECT_RECORD).dispatchTable
  473.       if dispTable == null
  474.         return 0
  475.       endIf
  476.  
  477.       classDesc = dispTable.classDescriptor
  478.  
  479.       -- Make sure the magic number is what we expect it to be.
  480.       if classDesc.magic != 0x434C4153   -- 'CLAS'
  481.         KPLSystemError ("WITHIN KPLIsKindOf: Bad Magic Number")
  482.       endIf
  483.  
  484.       -- Run through all supers.  (Each class is a super of itself.)
  485.       next = & classDesc.firstSuperPtr
  486.       while true
  487.         if *next == null
  488.           return 0
  489.         elseIf *next == typeDesc
  490.           return 1
  491.         endIf
  492.         next = next + 4
  493.       endWhile
  494.     endFunction
  495.  
  496. -----------------------------  KPLUncaughtThrow  ---------------------------------
  497.  
  498.   function KPLUncaughtThrow (errorID: ptr to char, line: int, rPtr: int)
  499.     --
  500.     -- Whenever an error is thrown but not caught, there will be an upcall from the
  501.     -- runtime system to this function.  (Exception: if "UncaughtThrowError" is thrown
  502.     -- but not caught, it will cause a fatal runtime error.)  This function will
  503.     -- print some info about the error that was thrown, then it will throw an
  504.     -- error called "UncaughtThrowError".  This error may or may not be caught by
  505.     -- the user's code.  If not, the runtime system will simply print an error and halt.
  506.     --
  507.       var
  508.         charPtr: ptr to char
  509.       print ("\n\n++++++++++ An error has been thrown but not caught ++++++++++\n")
  510.       print ("   Error Name = ")
  511.       printNullTerminatedString (errorID)
  512.       nl ()
  513.       print ("   Location at time of THROW = ")
  514.       charPtr = * (rPtr asPtrTo ptr to char)
  515.       printNullTerminatedString (charPtr)
  516.       print (":")
  517.       printInt (line)
  518.       nl ()
  519.       print ("   Currently active method or function = ")
  520.       rPtr = rPtr + 4
  521.       charPtr = * (rPtr asPtrTo ptr to char)
  522.       printNullTerminatedString (charPtr)
  523.       nl ()
  524.       printCatchStack ()
  525.       print ("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\n")
  526.       throw UncaughtThrowError (errorID, line, rPtr)
  527.     endFunction
  528.  
  529. -----------------------------  printCatchStack  ---------------------------------
  530.  
  531.   function printCatchStack ()
  532.     --
  533.     -- Print all CATCH_RECORDs on the CATCH_STACK.
  534.     --
  535.     -- NOTE: Whenever we leave the body statements in a try (i.e., fall-thru,
  536.     --       throw, or return), records from the catch stack will be popped and
  537.     --       freed.  "getCatchStack" returns a pointer to a list of CATCH_RECORDs
  538.     --       as it is when getCatchStack is called.  This routine merely reads data
  539.     --       from these records, so additional pushing and popping is okay and may
  540.     --       occur (e.g., we call "print", which may contain TRY statements).  However,
  541.     --       none of the records on the list returned by getCatchStack will be freed
  542.     --       before this routine is done looking at and printing them.
  543.     --
  544.     var p: ptr to CATCH_RECORD = getCatchStack () asPtrTo CATCH_RECORD
  545.       print ("   Here is the CATCH STACK:\n")
  546.       while p
  547.         print ("     ")
  548.         printNullTerminatedString (p.fileName)
  549.         print (":")
  550.         printInt (p. lineNumber)
  551.         print (":\t")
  552.         printNullTerminatedString (p.errorID)
  553.         --print ("\t\t(CATCH-RECORD addr = 0x")
  554.         --printHex (p asInteger)
  555.         --print (")")
  556.         nl ()
  557.         /**********
  558.         print ("     ")
  559.         printNullTerminatedString (p.errorID)
  560.         print ("\n        Source Filename:   ")
  561.         printNullTerminatedString (p.fileName)
  562.         print ("\n        Line number:       ")
  563.         printInt (p. lineNumber)
  564.         print ("\n        Catch record addr: ")
  565.         printHex (p asInteger)
  566.         print ("\n        Catch code addr:   ")
  567.         printHex (p.catchCodePtr)
  568.         print ("\n        Old FP:            ")
  569.         printHex (p.oldFP)
  570.         print ("\n        Old SP:            ")
  571.         printHex (p.oldSP)
  572.         nl ()
  573.         **********/
  574.         p = p.next
  575.       endWhile
  576.     endFunction
  577.  
  578. endCode
  579.