CAST II Game Engine |
||||||||
![]() |
MAIN | FEATURES | SCREENSHOTS | FORUMS | MANUAL | DOWNLOADS | CONTACTS | |
(C) 2006-2007 George "Mirage" Bakhtadze. www.casteng.com
The source code may be used under either MPL 1.1 or LGPL 2.1 license. See included license.txt file
Started Jul 15, 2004 The unit contains the compiler basic constants and types
| Name | Description |
|---|---|
Class TRTData |
function GetVTypeInt(Value: Int32): Int32; |
function GetVTypeInt(Value: Int32): Int32; |
Int = Integer; |
Int16 = SmallInt; |
Int32 = LongInt; |
Int8 = ShortInt; |
Nat = Cardinal; |
Nat16 = Word; |
Nat32 = LongWord; |
Nat8 = Byte; |
PDataPool = ^TDataPool; |
PNamespace = ^TNamespace; |
PType = ^TType; |
TCompilationError = record Source: string; Number, Line, Position: Integer; Data: Integer; end; |
TDataPool = array[0..MaxInt-1] of Byte; |
TIdent = packed record Name: TName; TypeID, Location, ExportMode, Index: Int32; Namespace: PNamespace; case StdProcedure: Boolean of True: (CommandID: Integer); False: (Size: Integer); end; |
TName = string[32]; |
TNamespace = record Name: TName; UID: Integer; Kind: Int32; ParamCount: Int32; ID: Int32; StackLength: Int32; TotalConstants, TotalVariables, TotalProcedures, TotalTypes: Int32; Constants, Variables, Types: array of Longword; Procedures: array of PNameSpace; Parent: PNamespace; end; |
TPIN = array of TPINItem; |
TPINItem = Integer; |
TType = record Name: TName; Kind: Int32; ID: Int32; Dimension, Size: Int32; Namespace: PNamespace; end; |
Int = Integer; |
Int16 = SmallInt; |
Int32 = LongInt; |
Int8 = ShortInt; |
Nat = Cardinal; |
Nat16 = Word; |
Nat32 = LongWord; |
Nat8 = Byte; |
PDataPool = ^TDataPool; |
PNamespace = ^TNamespace; |
PType = ^TType; |
TCompilationError = record Source: string; Number, Line, Position: Integer; Data: Integer; end; |
TDataPool = array[0..MaxInt-1] of Byte; |
TIdent = packed record Name: TName; TypeID, Location, ExportMode, Index: Int32; Namespace: PNamespace; case StdProcedure: Boolean of True: (CommandID: Integer); False: (Size: Integer); end; |
TName = string[32]; |
TPIN = array of TPINItem; |
TPINItem = Integer; |
TType = record Name: TName; Kind: Int32; ID: Int32; Dimension, Size: Int32; Namespace: PNamespace; end; |
TToken | ||
tNone | ||
tIdentifier | ||
tOperator | ||
tExpression | ||
tRelation | ||
tOperation | ||
tEndToken | ||
aoAddII = $80 + 1; |
aoAddIR = $80 + 2; |
aoAddRI = $80 + 3; |
aoAddRR = $80 + 4; |
aoAddSS = $80 + 105; |
aoAndBB = $80 + 20; |
aoAndII = $80 + 19; |
aoAssign1 = $80 + 54; |
aoAssign2 = $80 + 55; |
aoAssign4 = $80 + 56; |
aoAssign4RI = $80 + 57; |
aoAssignSize = $80 + 58; |
aoCall = $80 + 64; |
aoDivII = $80 + 13; |
aoDivIR = $80 + 14; |
aoDivRI = $80 + 15; |
aoDivRR = $80 + 16; |
aoDivSS = $80 + 117; |
aoExit = $80 + 67; |
aoExpandStack = $80 + 70; |
aoExtAssign1 = $80 + 71; |
aoExtAssign2 = $80 + 72; |
aoExtAssign4 = $80 + 73; |
aoExtAssign4RI = $80 + 74; |
aoExtAssignSize = $80 + 75; |
aoGoto = $80 + 62; |
aoIDivII = $80 + 21; |
aoInvB = $80 + 26; |
aoInvI = $80 + 25; |
aoJumpIfZero = $80 + 63; |
aoModII = $80 + 22; |
aoMulII = $80 + 9; |
aoMulIR = $80 + 10; |
aoMulRI = $80 + 11; |
aoMulRR = $80 + 12; |
aoMulSS = $80 + 113; |
aoNegI = $80 + 23; |
aoNegR = $80 + 24; |
aoNegS = $80 + 125; |
aoNull = $80 + 0; |
aoOrBB = $80 + 18; |
aoOrII = $80 + 17; |
aoReturnF = $80 + 65; |
aoReturnP = $80 + 66; |
aoSetStackBase = $80 + 69; |
aoStackAssign4 = $80 + 59; |
aoStackAssign4RI = $80 + 60; |
aoStackAssignSize = $80 + 61; |
aoSubII = $80 + 5; |
aoSubIR = $80 + 6; |
aoSubRI = $80 + 7; |
aoSubRR = $80 + 8; |
aoSubSS = $80 + 109; |
arEqualII = $80 + 28; |
arEqualIR = $80 + 29; |
arEqualRI = $80 + 30; |
arEqualRR = $80 + 31; |
arGreaterEqualII = $80 + 40; |
arGreaterEqualIR = $80 + 41; |
arGreaterEqualRI = $80 + 42; |
arGreaterEqualRR = $80 + 43; |
arGreaterII = $80 + 32; |
arGreaterIR = $80 + 33; |
arGreaterRI = $80 + 34; |
arGreaterRR = $80 + 35; |
arIn = $80 + 52; |
arIS = $80 + 53; |
arLessEqualII = $80 + 44; |
arLessEqualIR = $80 + 45; |
arLessEqualRI = $80 + 46; |
arLessEqualRR = $80 + 47; |
arLessII = $80 + 36; |
arLessIR = $80 + 37; |
arLessRI = $80 + 38; |
arLessRR = $80 + 39; |
arNotEqualII = $80 + 48; |
arNotEqualIR = $80 + 49; |
arNotEqualRI = $80 + 50; |
arNotEqualRR = $80 + 51; |
CommentStr : array[0..TotalComments-1] of record Open, Close: string[10]; end = ((Open: '(*'; Close: '*)'), (Open: '//'; Close: #10)); |
dConst = 1; |
DeclarationStr : array[0..TotalDeclarations-1] of string[9] = ('VAR', 'CONST', 'TYPE', 'PROCEDURE'); |
dProc = 3; |
dtArray = 16; |
dtBoolean = 0; |
dtChar = 1; |
dtConstant = 32; |
dtDouble = 12; |
dtExtVariable = 38; |
dtExtVariableByOfs = 40; |
dtExtVariableRef = 39; |
dtInt = 5; |
dtInt16 = 3; |
dtInt32 = 4; |
dtInt8 = 2; |
dtNat = 9; |
dtNat16 = 7; |
dtNat32 = 8; |
dtNat8 = 6; |
dtPointer = 18; |
dtProcedure = 19; |
dtReal = 11; |
dtRecord = 17; |
dtSet = 14; |
dtSingle = 10; |
dtStackVariable = 36; |
dtStackVariableByOfs = 37; |
dtString = 13; |
dtVariable = 33; |
dtVariableByOfs = 35; |
dtVariableRef = 34; |
dType = 2; |
dVar = 0; |
eAssignationExpected = 15; |
eBeginExpected = 28; |
eBooleanExpExpected = 21; |
eCannotAssign = 11; |
eColonExpected = 25; |
eConstExpExpected = 39; |
eDoExpected = 17; |
eEndExpected = 19; |
eEqualExpected = 27; |
eeSum = 1; |
eExternalVarUnknownType = 46; |
eIdentRedeclared = 23; |
eIncomparableTypes = 10; |
eIncompatibleTypes = 9; |
eInternalError = 40; |
eIntExpExpected = 41; |
eInvalidNumber = 47; |
eMustBeFunction = 35; |
eMustBeProcedure = 36; |
EndTokenStr : array[0..TotalEndTokens-1] of string[5] = ('END', 'DO', 'UNTIL', 'TO', 'EXIT', 'THEN', 'ELSIF', 'ELSE', 'OF'); |
eNotEnoughParameters = 33; |
eOfExpected = 43; |
eOperationExpected = 29; |
ePositiveIntExpExpected = 42; |
eProcNameMismatch = 32; |
eReturnExpected = 38; |
eRightBraceExpected = 31; |
eRightBracketExpected = 44; |
eRightParenthesisExpected = 30; |
eSemicolonExpected = 26; |
eSequenceEndNotFound = 13; |
etDo = 1; |
etElse = 7; |
etElseIf = 6; |
etEnd = 0; |
etExit = 4; |
eThenExpected = 20; |
eToExpected = 18; |
eTooManyParameters = 34; |
etThen = 5; |
etTo = 3; |
etUntil = 2; |
eUndeclaredIdentifier = 8; |
eUnexpectedBreak = 22; |
eUnexpectedExpEnd = 4; |
eUnexpectedExpression = 2; |
eUnexpectedIdentifier = 7; |
eUnexpectedNumber = 3; |
eUnexpectedOperation = 1; |
eUnexpectedOperator = 6; |
eUnexpectedResWord = 45; |
eUnexpectedReturn = 37; |
eUnexpectedSequenceEnd = 12; |
eUnexpectedSimbol = 5; |
eUnknownType = 24; |
eUntilExpected = 16; |
eVariableExpected = 14; |
exExpression = 2; |
exOperation = 3; |
exRelation = 4; |
ikConstant = 0; |
ikProcedure = 2; |
ikType = 3; |
ikVariable = 1; |
ilExternal = 2; |
ilGlobal = 0; |
ilStack = 1; |
nskModule = 0; |
nskProcedure = 1; |
nskRecord = 2; |
oAdd = $80 + 1; |
oAnd = $80 + 19; |
oAssign = $80 + 54; |
oDiv = $80 + 13; |
oIDiv = $80 + 21; |
oInv = $80 + 26; |
oMod = $80 + 22; |
oMul = $80 + 9; |
oNeg = $80 + 23; |
oOr = $80 + 17; |
Op1ID : array[0..TotalOperations1-1] of Cardinal = (oAdd, oSub, oOr); |
Op1Str : array[0..TotalOperations1-1] of string[3] = ('+', '-', 'OR'); |
Op2ID : array[0..TotalOperations2-1] of Cardinal = (oMul, oDiv, oAnd, oIDiv, oMod); |
Op2Str : array[0..TotalOperations2-1] of string[3] = ('*', '/', '&', 'DIV', 'MOD'); |
opAssign = 0; |
OperatorStr : array[0..TotalOperators-1] of string[6] = (':=', 'LOOP', 'WHILE', 'REPEAT', 'FOR', 'IF', 'EXIT', 'RETURN'); |
opExit = 6; |
opFor = 4; |
opIf = 5; |
opLopp = 1; |
opRepeat = 3; |
opReturn = 7; |
opWhile = 2; |
oSub = $80 + 5; |
RelationID : array[0..TotalRelations-1] of Cardinal = (rEqual, rGreater, rLess, rGreaterEqual, rLessEqual, rNotEqual, rIN, rIS); |
RelationStr : array[0..TotalRelations-1] of string[2] = ('=', '>', '<', '>=', '<=', '#', 'IN', 'IS'); |
rEqual = $80 + 28; |
ReservedWord : array[0..TotalReservedWords-1] of string[9] = ( 'ARRAY', 'BEGIN', 'BY', 'CASE', 'CONST', 'DIV', 'DO', 'ELSE', 'ELSEIF', 'END', 'EXIT', 'FOR', 'IF', 'IMPORT', 'IN', 'IS', 'LOOP', 'MOD', 'MODULE', 'NIL', 'OF', 'OR', 'POINTER', 'PROCEDURE', 'RECORD', 'REPEAT', 'RETURN', 'THEN', 'TO', 'TYPE', 'UNTIL', 'VAR', 'WHILE', 'WITH' ); |
rGreater = $80 + 32; |
rGreaterEqual = $80 + 40; |
rIN = $80 + 52; |
rIS = $80 + 53; |
rLess = $80 + 36; |
rLessEqual = $80 + 44; |
rNotEqual = $80 + 48; |
rteRangeError = 1; |
rteStackEmpty = 2; |
rtModule = -2; |
rtProcedure = -1; |
sfArcTan = $80 + 79; |
sfBlend = $80+85; |
sfCos = $80 + 77; |
sfEntier = $80 + 83; |
sfInvSqrt = $80 + 81; |
sfLn = $80+84; |
sfRnd = $80 + 82; |
sfSin = $80 + 76; |
sfSqrt = $80 + 80; |
sfTan = $80 + 78; |
StandardProcedureCommandIDs : array[0..TotalStandardProcedures-1] of Integer = ( sfSin, sfCos, sfTan, sfArcTan, sfSqrt, sfInvSqrt, sfRnd, sfEntier, sfLn, sfBlend ); |
tkArray = 1; |
tkCommon = 0; |
tkPointer = 3; |
tkProcedure = 4; |
tkRecord = 2; |
tmInt = 0; |
tmSingle = 256; |
TotalComments = 2; |
TotalDeclarations = 4; |
TotalEndTokens = 9; |
TotalErrors = 47; |
TotalOperations1 = 3; |
TotalOperations2 = 5; |
TotalOperators = 8; |
TotalRelations = 8; |
TotalReservedWords = 34; |
TotalStandardProcedures = 10; |
TotalSTDTypes = 15; |
TotalUnarOperations = 2; |
TypeStr : array[0..TotalSTDTypes-1] of string[8] = ('BOOLEAN', 'CHAR', 'SHORTINT', 'SMALLINT', 'LONGINT', 'INTEGER', 'SHORTINT', 'SMALLINT', 'LONGINT', 'INTEGER', 'SINGLE', 'REAL', 'LONGREAL', 'STRING', 'SET'); |
TypeToStr : array[1..15] of string[10] = ('Boolean', 'Char', 'Int8', 'Int16', 'Int32', 'Int', 'Nat8', 'Nat16', 'Nat32', 'Nat', 'Single', 'Double', 'Real', 'String', 'Set'); |
UnarOpID : array[0..TotalUnarOperations-1] of Cardinal = (oNeg, oInv); |
UnarOpStr : array[0..TotalUnarOperations-1] of string[3] = ('-', '~'); |
aoAddII = $80 + 1; |
aoAddIR = $80 + 2; |
aoAddRI = $80 + 3; |
aoAddRR = $80 + 4; |
aoAddSS = $80 + 105; |
aoAndBB = $80 + 20; |
aoAndII = $80 + 19; |
aoAssign1 = $80 + 54; |
Operators
aoAssign2 = $80 + 55; |
aoAssign4 = $80 + 56; |
aoAssign4RI = $80 + 57; |
aoAssignSize = $80 + 58; |
aoCall = $80 + 64; |
aoDivII = $80 + 13; |
aoDivIR = $80 + 14; |
aoDivRI = $80 + 15; |
aoDivRR = $80 + 16; |
aoDivSS = $80 + 117; |
aoExit = $80 + 67; |
aoExpandStack = $80 + 70; |
aoExtAssign1 = $80 + 71; |
Operations with external variables for scripting only
aoExtAssign2 = $80 + 72; |
aoExtAssign4 = $80 + 73; |
aoExtAssign4RI = $80 + 74; |
aoExtAssignSize = $80 + 75; |
aoGoto = $80 + 62; |
aoIDivII = $80 + 21; |
aoInvB = $80 + 26; |
aoInvI = $80 + 25; |
aoJumpIfZero = $80 + 63; |
aoModII = $80 + 22; |
aoMulII = $80 + 9; |
aoMulIR = $80 + 10; |
aoMulRI = $80 + 11; |
aoMulRR = $80 + 12; |
aoMulSS = $80 + 113; |
aoNegI = $80 + 23; |
aoNegR = $80 + 24; |
aoNegS = $80 + 125; |
aoNull = $80 + 0; |
All actions
aoOrBB = $80 + 18; |
aoOrII = $80 + 17; |
aoReturnF = $80 + 65; |
aoReturnP = $80 + 66; |
aoSetStackBase = $80 + 69; |
aoStackAssign4 = $80 + 59; |
aoStackAssign4RI = $80 + 60; |
aoStackAssignSize = $80 + 61; |
aoSubII = $80 + 5; |
aoSubIR = $80 + 6; |
aoSubRI = $80 + 7; |
aoSubRR = $80 + 8; |
aoSubSS = $80 + 109; |
arEqualII = $80 + 28; |
Relations
arEqualIR = $80 + 29; |
arEqualRI = $80 + 30; |
arEqualRR = $80 + 31; |
arGreaterEqualII = $80 + 40; |
arGreaterEqualIR = $80 + 41; |
arGreaterEqualRI = $80 + 42; |
arGreaterEqualRR = $80 + 43; |
arGreaterII = $80 + 32; |
arGreaterIR = $80 + 33; |
arGreaterRI = $80 + 34; |
arGreaterRR = $80 + 35; |
arIn = $80 + 52; |
arIS = $80 + 53; |
arLessEqualII = $80 + 44; |
arLessEqualIR = $80 + 45; |
arLessEqualRI = $80 + 46; |
arLessEqualRR = $80 + 47; |
arLessII = $80 + 36; |
arLessIR = $80 + 37; |
arLessRI = $80 + 38; |
arLessRR = $80 + 39; |
arNotEqualII = $80 + 48; |
arNotEqualIR = $80 + 49; |
arNotEqualRI = $80 + 50; |
arNotEqualRR = $80 + 51; |
CommentStr : array[0..TotalComments-1] of record Open, Close: string[10]; end = ((Open: '(*'; Close: '*)'), (Open: '//'; Close: #10)); |
dConst = 1; |
DeclarationStr : array[0..TotalDeclarations-1] of string[9] = ('VAR', 'CONST', 'TYPE', 'PROCEDURE'); |
dProc = 3; |
dtArray = 16; |
dtBoolean = 0; |
// Types. Must be in size-accending order
dtChar = 1; |
dtConstant = 32; |
dtDouble = 12; |
dtExtVariable = 38; |
dtExtVariableByOfs = 40; |
dtExtVariableRef = 39; |
dtInt = 5; |
dtInt16 = 3; |
dtInt32 = 4; |
dtInt8 = 2; |
dtNat = 9; |
dtNat16 = 7; |
dtNat32 = 8; |
dtNat8 = 6; |
dtPointer = 18; |
dtProcedure = 19; |
dtReal = 11; |
dtRecord = 17; |
dtSet = 14; |
dtSingle = 10; |
dtStackVariable = 36; |
dtStackVariableByOfs = 37; |
dtString = 13; |
dtVariable = 33; |
dtVariableByOfs = 35; |
dtVariableRef = 34; |
dType = 2; |
dVar = 0; |
eAssignationExpected = 15; |
eBeginExpected = 28; |
eBooleanExpExpected = 21; |
eCannotAssign = 11; |
eColonExpected = 25; |
eConstExpExpected = 39; |
eDoExpected = 17; |
eEndExpected = 19; |
eEqualExpected = 27; |
eeSum = 1; |
eExternalVarUnknownType = 46; |
eIdentRedeclared = 23; |
eIncomparableTypes = 10; |
eIncompatibleTypes = 9; |
eInternalError = 40; |
eIntExpExpected = 41; |
eInvalidNumber = 47; |
eMustBeFunction = 35; |
eMustBeProcedure = 36; |
EndTokenStr : array[0..TotalEndTokens-1] of string[5] = ('END', 'DO', 'UNTIL', 'TO', 'EXIT', 'THEN', 'ELSIF', 'ELSE', 'OF'); |
eNotEnoughParameters = 33; |
eOfExpected = 43; |
eOperationExpected = 29; |
ePositiveIntExpExpected = 42; |
eProcNameMismatch = 32; |
eReturnExpected = 38; |
eRightBraceExpected = 31; |
eRightBracketExpected = 44; |
eRightParenthesisExpected = 30; |
eSemicolonExpected = 26; |
eSequenceEndNotFound = 13; |
etDo = 1; |
etElse = 7; |
etElseIf = 6; |
etEnd = 0; |
etExit = 4; |
eThenExpected = 20; |
eToExpected = 18; |
eTooManyParameters = 34; |
etThen = 5; |
etTo = 3; |
etUntil = 2; |
eUndeclaredIdentifier = 8; |
eUnexpectedBreak = 22; |
eUnexpectedExpEnd = 4; |
eUnexpectedExpression = 2; |
eUnexpectedIdentifier = 7; |
eUnexpectedNumber = 3; |
eUnexpectedOperation = 1; |
Compile errors
eUnexpectedOperator = 6; |
eUnexpectedResWord = 45; |
eUnexpectedReturn = 37; |
eUnexpectedSequenceEnd = 12; |
eUnexpectedSimbol = 5; |
eUnknownType = 24; |
eUntilExpected = 16; |
eVariableExpected = 14; |
exExpression = 2; |
exOperation = 3; |
exRelation = 4; |
ikConstant = 0; |
ikProcedure = 2; |
ikType = 3; |
ikVariable = 1; |
ilExternal = 2; |
ilGlobal = 0; |
Ident location
ilStack = 1; |
nskModule = 0; |
Namespace kind
nskProcedure = 1; |
nskRecord = 2; |
oAdd = $80 + 1; |
Operations
oAnd = $80 + 19; |
oAssign = $80 + 54; |
Operators
oDiv = $80 + 13; |
oIDiv = $80 + 21; |
oInv = $80 + 26; |
oMod = $80 + 22; |
oMul = $80 + 9; |
oNeg = $80 + 23; |
oOr = $80 + 17; |
Op1ID : array[0..TotalOperations1-1] of Cardinal = (oAdd, oSub, oOr); |
Op1Str : array[0..TotalOperations1-1] of string[3] = ('+', '-', 'OR'); |
Op2ID : array[0..TotalOperations2-1] of Cardinal = (oMul, oDiv, oAnd, oIDiv, oMod); |
Op2Str : array[0..TotalOperations2-1] of string[3] = ('*', '/', '&', 'DIV', 'MOD'); |
opAssign = 0; |
OperatorStr : array[0..TotalOperators-1] of string[6] = (':=', 'LOOP', 'WHILE', 'REPEAT', 'FOR', 'IF', 'EXIT', 'RETURN'); |
opExit = 6; |
opFor = 4; |
opIf = 5; |
opLopp = 1; |
opRepeat = 3; |
opReturn = 7; |
opWhile = 2; |
oSub = $80 + 5; |
RelationID : array[0..TotalRelations-1] of Cardinal = (rEqual, rGreater, rLess, rGreaterEqual, rLessEqual, rNotEqual, rIN, rIS); |
RelationStr : array[0..TotalRelations-1] of string[2] = ('=', '>', '<', '>=', '<=', '#', 'IN', 'IS'); |
rEqual = $80 + 28; |
rGreater = $80 + 32; |
rGreaterEqual = $80 + 40; |
rIN = $80 + 52; |
rIS = $80 + 53; |
rLess = $80 + 36; |
rLessEqual = $80 + 44; |
rNotEqual = $80 + 48; |
rteRangeError = 1; |
Runtime errors
rteStackEmpty = 2; |
rtModule = -2; |
Result types
rtProcedure = -1; |
sfArcTan = $80 + 79; |
sfBlend = $80+85; |
sfCos = $80 + 77; |
sfEntier = $80 + 83; |
sfInvSqrt = $80 + 81; |
sfLn = $80+84; |
sfRnd = $80 + 82; |
sfSin = $80 + 76; |
Standard functions
sfSqrt = $80 + 80; |
sfTan = $80 + 78; |
StandardProcedureCommandIDs : array[0..TotalStandardProcedures-1] of Integer = ( sfSin, sfCos, sfTan, sfArcTan, sfSqrt, sfInvSqrt, sfRnd, sfEntier, sfLn, sfBlend ); |
tkArray = 1; |
tkCommon = 0; |
Type kind
tkPointer = 3; |
tkProcedure = 4; |
tkRecord = 2; |
tmInt = 0; |
Type modifiers
tmSingle = 256; |
TotalComments = 2; |
Comments
TotalDeclarations = 4; |
TotalEndTokens = 9; |
TotalErrors = 47; |
TotalOperations1 = 3; |
TotalOperations2 = 5; |
TotalOperators = 8; |
TotalRelations = 8; |
TotalReservedWords = 34; |
TotalStandardProcedures = 10; |
TotalSTDTypes = 15; |
TotalUnarOperations = 2; |
TypeToStr : array[1..15] of string[10] = ('Boolean', 'Char', 'Int8', 'Int16', 'Int32', 'Int', 'Nat8', 'Nat16', 'Nat32', 'Nat', 'Single', 'Double', 'Real', 'String', 'Set'); |
UnarOpID : array[0..TotalUnarOperations-1] of Cardinal = (oNeg, oInv); |
UnarOpStr : array[0..TotalUnarOperations-1] of string[3] = ('-', '~'); |
|
Last modified: 26 Oct, 2008 |