String Operations
Constant strings are added in the temporary buffer, while all non-constant string operations are performed in stack frame.
Procedure ConstantStringOperations;
Var BoolResult: LongBool;
LeftString, RightString: PString;
CommonLength, NewStringOffset: Word;
begin
LeftString := Ptr (DSeg, LeftExpression.Value.Word);
RightString := Ptr (DSeg, RightExpression.Value.Word);
Case Operation of
Calc_Add: begin
If (Ofs (LeftString^) + Length (LeftString^) + 1 = Ofs (RightString^)) and
(Ofs (RightString^) + Length (RightString^) + 1 = TempBufferFreePositionOffset) then
TempBufferFreePositionOffset := Ofs (LeftString^);
CommonLength := Length (LeftString^) + Length (RightString^);
If CommonLength > $FF then CommonLength := $FF;
NewStringOffset := GetTempBufferOffset (CommonLength + 1);
PString (Ptr (DSeg, NewStringOffset))^ := LeftString^ + RightString^;
LeftExpression.Value.Word := NewStringOffset;
end;
else begin
Case Operation of
Calc_IsEqual: BoolResult := LeftString^ = RightString^;
Calc_IsNotEqual: BoolResult := LeftString^ <> RightString^;
Calc_IsGreater: BoolResult := LeftString^ > RightString^;
Calc_IsLower: BoolResult := LeftString^ > RightString^;
Calc_IsGreaterOrEqual: BoolResult := LeftString^ >= RightString^;
Calc_IsLowerOrEqual: BoolResult := LeftString^ <= RightString^;
end;
SetLeftExpressionToConstantBooleanValue (BoolResult);
end;
end;
end;
Procedure GenerateCodeForStringOperations;
Label NoEmptyString;
begin
Case Operation of
Calc_ADD: begin
LeftExpression.CopyStringToStackFrame ($0100);
RightExpression.StoreStringConstantToCodeBlock;
ConvertToPointerAndPushBothExpressions (LeftExpression, RightExpression);
CalculateBothExpressions (LeftExpression, RightExpression);
GenerateInstruction_CALL_FAR (SysProc_SConcat);
With LeftExpression do
begin
LeftExpression.EndIntermediateCodeSubroutine;
UsedRegisters := [urBX, urDX, urCX, urAX];
end;
end;
else begin
If (RightExpression.Location <> elConstant) or (PString (Ptr (DSeg, RightExpression.Value.Word))^ <> '') then
begin
If (LeftExpression.Location <> elConstant) then GoTo NoEmptyString;
ExchangeLeftAndRightExpression;
If PString (Ptr (DSeg, RightExpression.Value.Word))^ <> '' then GoTo NoEmptyString;
end;
LeftExpression.PositionToStringLength;
With RightExpression do
begin
DataType := [];
Value.LongInt := 0;
end;
GenerateCodeForIntegerComparisons;
LeftExpression.EndIntermediateCodeSubroutine;
Exit;
NoEmptyString:
LeftExpression.StoreStringConstantToCodeBlock;
RightExpression.StoreStringConstantToCodeBlock;
ConvertToPointerAndPushBothExpressions (LeftExpression, RightExpression);
CalculateBothExpressions (LeftExpression, RightExpression);
GenerateInstruction_CALL_FAR (SysProc_SCompare);
With LeftExpression do
begin
LeftExpression.EndIntermediateCodeSubroutine;
UsedRegisters := [urBX, urDX, urCX, urAX];
end;
LeftExpression.SetExpressionToBooleanJump (UnsignedConditionalJumpOpCode [Operation]);
end;
end;
end;