|
|
@@ -1816,7 +1816,7 @@ PRODUCTIONS
|
|
|
(. VAR t2, res2, lt, rt:
|
|
|
SymTab.TypeIndex;
|
|
|
op: INTEGER;
|
|
|
- q2, qt, wq, qf:
|
|
|
+ q2, qt, wq, qf, q2a, q2b:
|
|
|
QbeGen.QVal;
|
|
|
neg, isR, isL, folded:
|
|
|
BOOLEAN;
|
|
|
@@ -1862,6 +1862,31 @@ PRODUCTIONS
|
|
|
QbeGen.CopyOp(qr, q)
|
|
|
ELSE QbeGen.DelayFlush; QbeGen.CopyOp("0", q)
|
|
|
END
|
|
|
+ ELSIF (op = SymTab.OpAdd)
|
|
|
+ AND (SymTab.UStrCompat(t, t2)
|
|
|
+ OR ((SymTab.ClassOf(t) = SymTab.ClUChar)
|
|
|
+ AND (SymTab.ClassOf(t2) = SymTab.ClUStr))
|
|
|
+ OR ((SymTab.ClassOf(t) = SymTab.ClUStr)
|
|
|
+ AND (SymTab.ClassOf(t2) = SymTab.ClUChar))
|
|
|
+ OR ((SymTab.ClassOf(t) = SymTab.ClUChar)
|
|
|
+ AND (SymTab.ClassOf(t2) = SymTab.ClUChar))) THEN
|
|
|
+ (* UString concatenation: a UCHAR operand becomes a
|
|
|
+ 1-codepoint UString; the result is a descriptor in the
|
|
|
+ shim's concat buffer. Work on copies so neither
|
|
|
+ operand is clobbered. *)
|
|
|
+ IF SymTab.ClassOf(t) = SymTab.ClUStr THEN
|
|
|
+ QbeGen.CopyOp(q, q2a)
|
|
|
+ ELSE
|
|
|
+ QbeGen.UStrFrom(q, q2a)
|
|
|
+ END;
|
|
|
+ IF SymTab.ClassOf(t2) = SymTab.ClUStr THEN
|
|
|
+ QbeGen.UStrCat(q2a, q2, qt)
|
|
|
+ ELSE
|
|
|
+ QbeGen.UStrFrom(q2, q2b);
|
|
|
+ QbeGen.UStrCat(q2a, q2b, qt)
|
|
|
+ END;
|
|
|
+ t := SymTab.NewUStr();
|
|
|
+ QbeGen.CopyOp(qt, q)
|
|
|
ELSIF (op = SymTab.OpAdd)
|
|
|
AND (SymTab.StrCompat(t, t2)
|
|
|
OR (SymTab.IsStrType(t)
|
|
|
@@ -2178,9 +2203,11 @@ PRODUCTIONS
|
|
|
END; .)
|
|
|
| ( "HIGH" (. isHigh := TRUE; .)
|
|
|
| ( "LEN" | "LENGTH" ) (. isHigh := FALSE; .) )
|
|
|
- "(" ( Design<dt, dk, qd, qn, sfx> (. isStr := FALSE; .)
|
|
|
+ "(" ( Design<dt, dk, qd, qn, sfx> (. isStr := FALSE;
|
|
|
+ isU := FALSE; .)
|
|
|
| string (. LexString(s);
|
|
|
isStr := TRUE;
|
|
|
+ isU := FALSE;
|
|
|
IF SymTab.StrLen(s) = 3 THEN
|
|
|
dt := SymTab.CharType();
|
|
|
QbeGen.IntStr(QbeGen.CharVal(s),
|
|
|
@@ -2191,9 +2218,49 @@ PRODUCTIONS
|
|
|
QbeGen.NoteAddr(qd, qd)
|
|
|
END;
|
|
|
dk := -1;
|
|
|
+ qn[0] := CHR(0); .)
|
|
|
+ | ustring (. LexString(s);
|
|
|
+ QbeGen.DeclUStr(s, qd, isU, ucp,
|
|
|
+ uok);
|
|
|
+ isStr := FALSE;
|
|
|
+ IF NOT uok THEN
|
|
|
+ SemError(234);
|
|
|
+ dt := SymTab.InvalidType
|
|
|
+ ELSIF isU THEN
|
|
|
+ (* one codepoint: a UCHAR;
|
|
|
+ LEN is 1, HIGH is 0 *)
|
|
|
+ dt := SymTab.UCharType();
|
|
|
+ QbeGen.IntStr(ucp, qd)
|
|
|
+ ELSE
|
|
|
+ dt := SymTab.NewUStr();
|
|
|
+ QbeGen.NoteAddr(qd, qd)
|
|
|
+ END;
|
|
|
+ dk := -1;
|
|
|
qn[0] := CHR(0); .) )
|
|
|
")"
|
|
|
- (. IF isStr THEN
|
|
|
+ (. IF (dt # SymTab.InvalidType)
|
|
|
+ AND (SymTab.ClassOf(dt) = SymTab.ClUStr) THEN
|
|
|
+ (* UString: the count is
|
|
|
+ the descriptor header *)
|
|
|
+ IF isHigh THEN
|
|
|
+ QbeGen.UStrLen(qd, qr);
|
|
|
+ QbeGen.DecQ(qr)
|
|
|
+ ELSE
|
|
|
+ QbeGen.UStrLen(qd, qr)
|
|
|
+ END;
|
|
|
+ t := SymTab.IntType();
|
|
|
+ QbeGen.CopyOp(qr, q)
|
|
|
+ ELSIF (dt # SymTab.InvalidType)
|
|
|
+ AND (SymTab.ClassOf(dt) = SymTab.ClUChar) THEN
|
|
|
+ (* single UCHAR codepoint *)
|
|
|
+ IF isHigh THEN
|
|
|
+ QbeGen.CopyOp("0", qr)
|
|
|
+ ELSE
|
|
|
+ QbeGen.CopyOp("1", qr)
|
|
|
+ END;
|
|
|
+ t := SymTab.IntType();
|
|
|
+ QbeGen.CopyOp(qr, q)
|
|
|
+ ELSIF isStr THEN
|
|
|
(* fold: content length at
|
|
|
compile time *)
|
|
|
IF SymTab.StrLen(s) = 3 THEN
|