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 / version-1-0 / OSProject / p2 / System.c < prev    next >
Text File  |  2006-09-25  |  18KB  |  537 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. ------------------------------------  THE HEAP  ---------------------------------
  228.  
  229.   -- The following functions (provided below) are used to implement the heap.
  230.   --    KPLSystemInitialize
  231.   --    KPLMemoryAlloc
  232.   --    KPLMemoryFree
  233.   -- The runtime system will execute calls to these routines whenever:
  234.   --    Whenever a TRY statement is executed
  235.   --    Whenever an ALLOC statement is executed
  236.   --    Whenever a FREE statement is executed
  237.   --
  238.   -- The heap implementation provided here is overly simple: Blocks of memory
  239.   -- are allocated sequentially and any attempt to "free" memory is ignored.
  240.   --
  241.   const
  242.     HEAP_SIZE = 20000
  243.   var
  244.     memoryArea: array [HEAP_SIZE] of char
  245.     nextCharToUse: int = 0
  246.     alreadyInAlloc: bool = false          -- Used to detect re-entrance
  247.  
  248. -----------------------------  KPLSystemInitialize  ---------------------------------
  249.  
  250.   function KPLSystemInitialize ()
  251.     --
  252.     -- This routine is called directly before the "main" function is called.
  253.     --
  254.     -- Initialize the array count without initializing the data.  Here we initialize
  255.     -- a few of the bytes in the HEAP so that we can watch out for overflowing
  256.     -- into the frame region.
  257.     --
  258.     var p: ptr to int = (& memoryArea) asPtrTo int
  259.         p2: ptr to int
  260.       *p = HEAP_SIZE
  261.       for p2 = p+4 to p + 4 + HEAP_SIZE-1 by 100
  262.         *p2 = 0x48454150      -- ASCII codes for "HEAP"
  263.       endFor
  264.     endFunction
  265.  
  266. -----------------------------  KPLMemoryAlloc  ---------------------------------
  267.  
  268.   function KPLMemoryAlloc (byteCount: int) returns ptr to char
  269.     --
  270.     -- This routine is called to allocate memory from the heap.
  271.     -- This heap implementation is trivial: It allocates space
  272.     -- sequentially, until there is no more.  When space is exhausted,
  273.     -- we throw an error.
  274.     --
  275.     -- NOTE: THIS FUNCTION IS ***NOT*** RE-ENTRANT!!!  The caller must
  276.     --       ensure that it will only be called from one thread.  (If it might
  277.     --       be called from different threads, the caller must ensure that it
  278.     --       is protected with semaphores, mutexes, etc. from being invoked
  279.     --       while it is already active!!!
  280.     --
  281.     var i: int
  282.         p: ptr to char
  283.  
  284.       -- The following test is NOT correct!!!  But it may
  285.       -- detect some cases of re-entrance...
  286.       if alreadyInAlloc
  287.         KPLSystemError ("WITHIN KPLMemoryAlloc: Reentered")
  288.       endIf
  289.       alreadyInAlloc = true
  290.  
  291.       i = nextCharToUse
  292.       if byteCount <= 0
  293.         print ("\n\nBad byteCount = ")
  294.         printInt (byteCount)
  295.         KPLSystemError ("WITHIN KPLMemoryAlloc: byte count is not positive")
  296.       endIf
  297.  
  298.       -- Add 4 bytes to the byte count, for storing a hidden byte count.
  299.       byteCount = byteCount + 4
  300.  
  301.       -- Round up to a multiple of 8.
  302.       if byteCount % 8 > 0
  303.         byteCount = (byteCount / 8 + 1) * 8
  304.       endIf
  305.  
  306.       -- Uncomment the following to see when "HEAP Alloc" occurs
  307.       /*
  308.       print ("\n+++++ KPLMemoryAlloc   byteCount: ")
  309.       printInt (byteCount)
  310.       print (", remaining: ")
  311.       printInt (HEAP_SIZE-(nextCharToUse + byteCount))
  312.       print (", returns: ")
  313.       printHex ((& (memoryArea [i])) asInteger + 4)
  314.       print (" +++++\n")
  315.       */
  316.  
  317.       nextCharToUse = nextCharToUse + byteCount
  318.       if nextCharToUse > HEAP_SIZE
  319.         KPLSystemError ("WITHIN KPLMemoryAlloc: Out of memory")
  320.       endIf
  321.       p = & (memoryArea [i])
  322.       *(p asPtrTo int) = byteCount
  323.  
  324.       alreadyInAlloc = false
  325.  
  326.       return p + 4
  327.  
  328.     endFunction
  329.  
  330. -----------------------------  KPLMemoryFree  ---------------------------------
  331.  
  332.   function KPLMemoryFree (p: ptr to char)
  333.     --
  334.     -- This routine is called to free memory in the heap.  It is passed a
  335.     -- pointer to a block of memory previously allocated in a call to "alloc".
  336.     --
  337.     -- Currently, this routine is a nop.
  338.     --
  339.       --print ("\n+++++ KPLMemoryFree called... ptr: ")
  340.       --printHex (p asInteger)
  341.       --print (" +++++\n")
  342.     endFunction
  343.  
  344. -----------------------------  KPLSystemError  ---------------------------------
  345.  
  346.   function KPLSystemError (message: ptr to array of char)
  347.     --
  348.     -- Come here when a fatal error occurs.  Print a message and terminate
  349.     -- the KPL program.  There will be no return from this function.
  350.     -- NOTE: This function is not aware of threads; it is better to use FatalError
  351.     -- (from the Thread package) if possible.
  352.     --
  353.       print ("\n\nFATAL KPL RUNTIME ERROR: ")
  354.       print (message)
  355.       nl ()
  356.       RuntimeExit ()
  357.     endFunction
  358.  
  359. ------------------------  Internal Runtime Data Structures  ------------------------
  360.   --
  361.   -- These data structures are intimately connected with the language
  362.   -- implementation and the compiler, and can safely be ignored by
  363.   -- KPL programmers.  They should not be changed without appropriate
  364.   -- modifications to the compiler.
  365.   --
  366.   type
  367.     -- The following record has a fixed format:
  368.     CATCH_RECORD = record
  369.                      next: ptr to CATCH_RECORD
  370.                      errorID: ptr to char    -- Null terminated string
  371.                      catchCodePtr: int       -- Address of the code
  372.                      oldFP: int
  373.                      oldSP: int
  374.                      fileName: ptr to char   -- Null terminated string
  375.                      lineNumber: int
  376.                    endRecord
  377.  
  378.     -- The following record has a fixed format:
  379.     DISPATCH_TABLE = record
  380.                        classDescriptor: ptr to CLASS_DESCRIPTOR
  381.                        firstMethodPtr: int    -- Address of code
  382.                      endRecord
  383.  
  384.     -- The following record has a fixed format:
  385.     CLASS_DESCRIPTOR = record
  386.                          magic: int                -- Should be 0x434C4153 == 'CLAS'
  387.                          myName: ptr to char       -- Null terminated string
  388.                          fileName: ptr to char     -- Null terminated string
  389.                          lineNumber: int
  390.                          sizeInBytes: int
  391.                          firstSuperPtr: ptr to DISPATCH_TABLE
  392.                        endRecord
  393.  
  394.     -- The following record has a fixed format:
  395.     INTERFACE_DESCRIPTOR = record
  396.                              magic: int                -- Should be 0x494E5446 == 'INTF'
  397.                              myName: ptr to char       -- Null terminated string
  398.                              fileName: ptr to char     -- Null terminated string
  399.                              lineNumber: int
  400.                              firstInterfacePtr: ptr to INTERFACE_DESCRIPTOR
  401.                            endRecord
  402.  
  403.     -- The following record has a fixed format:
  404.     OBJECT_RECORD = record
  405.                       dispatchTable: ptr to DISPATCH_TABLE
  406.                       firstField: int
  407.                     endRecord
  408.  
  409. -----------------------------  KPLIsKindOf  ---------------------------------
  410.  
  411.   function KPLIsKindOf (objPtr: ptr to Object, typeDesc: ptr to int) returns int
  412.     --
  413.     -- There will be an upcall from the runtime system to this function, which
  414.     -- will evaluate the "isKindOf" relation.  This routine determines whether
  415.     -- the object pointed to satisfies the "isKindOf" relation, i.e., whether it
  416.     -- is an instance of the given type, or of one of its super-classes or super-
  417.     -- interfaces.  It returns either 0 (for FALSE) or 1 (for TRUE).
  418.     --
  419.       var
  420.         dispTable: ptr to DISPATCH_TABLE
  421.         classDesc: ptr to CLASS_DESCRIPTOR
  422.         next: ptr to ptr to void
  423.    
  424.       -- We should never be passed a NULL pointer, but check anyway.
  425.       if objPtr == null
  426.         KPLSystemError ("WITHIN KPLIsKindOf: objPtr is NULL")
  427.       endIf
  428.  
  429.       -- If the object is uninitialized return false.
  430.       dispTable = (objPtr asPtrTo OBJECT_RECORD).dispatchTable
  431.       if dispTable == null
  432.         return 0
  433.       endIf
  434.  
  435.       classDesc = dispTable.classDescriptor
  436.  
  437.       -- Make sure the magic number is what we expect it to be.
  438.       if classDesc.magic != 0x434C4153   -- 'CLAS'
  439.         KPLSystemError ("WITHIN KPLIsKindOf: Bad Magic Number")
  440.       endIf
  441.  
  442.       -- Run through all supers.  (Each class is a super of itself.)
  443.       next = & classDesc.firstSuperPtr
  444.       while true
  445.         if *next == null
  446.           return 0
  447.         elseIf *next == typeDesc
  448.           return 1
  449.         endIf
  450.         next = next + 4
  451.       endWhile
  452.     endFunction
  453.  
  454. -----------------------------  KPLUncaughtThrow  ---------------------------------
  455.  
  456.   function KPLUncaughtThrow (errorID: ptr to char, line: int, rPtr: int)
  457.     --
  458.     -- Whenever an error is thrown but not caught, there will be an upcall from the
  459.     -- runtime system to this function.  (Exception: if "UncaughtThrowError" is thrown
  460.     -- but not caught, it will cause a fatal runtime error.)  This function will
  461.     -- print some info about the error that was thrown, then it will throw an
  462.     -- error called "UncaughtThrowError".  This error may or may not be caught by
  463.     -- the user's code.  If not, the runtime system will simply print an error and halt.
  464.     --
  465.       var
  466.         charPtr: ptr to char
  467.       print ("\n\n++++++++++ An error has been thrown but not caught ++++++++++\n")
  468.       print ("   Error Name = ")
  469.       printNullTerminatedString (errorID)
  470.       nl ()
  471.       print ("   Location at time of THROW = ")
  472.       charPtr = * (rPtr asPtrTo ptr to char)
  473.       printNullTerminatedString (charPtr)
  474.       print (":")
  475.       printInt (line)
  476.       nl ()
  477.       print ("   Currently active method or function = ")
  478.       rPtr = rPtr + 4
  479.       charPtr = * (rPtr asPtrTo ptr to char)
  480.       printNullTerminatedString (charPtr)
  481.       nl ()
  482.       printCatchStack ()
  483.       print ("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\n")
  484.       throw UncaughtThrowError (errorID, line, rPtr)
  485.     endFunction
  486.  
  487. -----------------------------  printCatchStack  ---------------------------------
  488.  
  489.   function printCatchStack ()
  490.     --
  491.     -- Print all CATCH_RECORDs on the CATCH_STACK.
  492.     --
  493.     -- NOTE: Whenever we leave the body statements in a try (i.e., fall-thru,
  494.     --       throw, or return), records from the catch stack will be popped and
  495.     --       freed.  "getCatchStack" returns a pointer to a list of CATCH_RECORDs
  496.     --       as it is when getCatchStack is called.  This routine merely reads data
  497.     --       from these records, so additional pushing and popping is okay and may
  498.     --       occur (e.g., we call "print", which may contain TRY statements).  However,
  499.     --       none of the records on the list returned by getCatchStack will be freed
  500.     --       before this routine is done looking at and printing them.
  501.     --
  502.     var p: ptr to CATCH_RECORD = getCatchStack () asPtrTo CATCH_RECORD
  503.       print ("   Here is the CATCH STACK:\n")
  504.       while p
  505.         print ("     ")
  506.         printNullTerminatedString (p.fileName)
  507.         print (":")
  508.         printInt (p. lineNumber)
  509.         print (":\t")
  510.         printNullTerminatedString (p.errorID)
  511.         --print ("\t\t(CATCH-RECORD addr = 0x")
  512.         --printHex (p asInteger)
  513.         --print (")")
  514.         nl ()
  515.         /**********
  516.         print ("     ")
  517.         printNullTerminatedString (p.errorID)
  518.         print ("\n        Source Filename:   ")
  519.         printNullTerminatedString (p.fileName)
  520.         print ("\n        Line number:       ")
  521.         printInt (p. lineNumber)
  522.         print ("\n        Catch record addr: ")
  523.         printHex (p asInteger)
  524.         print ("\n        Catch code addr:   ")
  525.         printHex (p.catchCodePtr)
  526.         print ("\n        Old FP:            ")
  527.         printHex (p.oldFP)
  528.         print ("\n        Old SP:            ")
  529.         printHex (p.oldSP)
  530.         nl ()
  531.         **********/
  532.         p = p.next
  533.       endWhile
  534.     endFunction
  535.  
  536. endCode
  537.