(* Copyright (C) 1992, Digital Equipment Corporation *) (* All rights reserved. *) (* See the file COPYRIGHT for a full description. *) (* File: TextExpr.m3 *) (* Last modified on Wed Sep 9 16:42:37 PDT 1992 by kalsow *) (* modified on Sun Feb 24 04:07:17 1991 by muller *) MODULE TextExpr; IMPORT Expr, ExprRep, String, Textt, Emit, Temp, Type, MBuf; CONST TextTypecode = 1; MaxCLiteral = 200; (* 'cause many C compilers choke on long string literals *) TYPE P = Expr.T OBJECT value : String.T; OVERRIDES typeOf := ExprRep.NoType; check := ExprRep.NoCheck; compile := Compile; evaluate := ExprRep.Self; fprint := FPrinter; write := Writer; isEqual := EqCheck; getBounds := ExprRep.NoBounds; isWritable := ExprRep.IsNever; isDesignator := ExprRep.IsNever; isZeroes := IsZeroes; note_write := ExprRep.NotWritable; genLiteral := GenLiteral; END; VAR nextID: INTEGER := 0; PROCEDURE Reset () = BEGIN nextID := 0; END Reset; PROCEDURE New (value: String.T): Expr.T = VAR p := NEW (P); BEGIN ExprRep.Init (p); p.value := value; p.type := Textt.T; p.checked := TRUE; RETURN p; END New; PROCEDURE EqCheck (a: P; e: Expr.T): BOOLEAN = BEGIN TYPECASE e OF | NULL => RETURN FALSE; | P(b) => RETURN (a.value = b.value); ELSE RETURN FALSE; END; END EqCheck; PROCEDURE SetUID (p: P) = VAR save: Emit.Stream; uid: INTEGER; BEGIN IF (String.GetUID (p.value) < 0) THEN (* generate the literal *) save := Emit.Switch (Emit.Stream.TextLiterals); uid := nextID; INC (nextID); String.SetUID (p.value, uid); IF (String.Length (p.value) < MaxCLiteral) THEN Emit.OpI ("_PRIVATE _TXT _txt@ = ", uid); EmitRep (p.value); Emit.Op (";\n"); ELSE Emit.OpI ("_PRIVATE char __txt@[] = ", uid); Emit.OpQ ("{\001\n@, 0\002\n};", p.value); Emit.OpI ("_PRIVATE _TXT _txt@ = ", uid); Emit.OpI ("{ {0, @},", TextTypecode); Emit.OpI ("__txt@, ", uid); Emit.OpI ("@};\n", String.Length (p.value) + 1); END; EVAL Emit.Switch (save); END; END SetUID; PROCEDURE EmitRep (s: String.T) = VAR len := String.Length (s); BEGIN Emit.OpI ("{ {0, @},", TextTypecode); IF (len < 45) THEN Emit.OpSI (" \"@\", @}", s, len+1); ELSE Emit.OpSI ("\001\n\"@\",\n@\002\n}", s, len+1); END; END EmitRep; PROCEDURE Compile (p: P): Temp.T = BEGIN RETURN Temp.FromExpr (p); END Compile; PROCEDURE Writer (p: P; <*UNUSED*> t1, t2: Temp.T) = BEGIN SetUID (p); Emit.OpI ("((_ADDRESS)(& _txt@.str))", String.GetUID (p.value)); END Writer; PROCEDURE GenLiteral (p: P) = BEGIN SetUID (p); Emit.OpI ("((_ADDRESS)(& _txt@.str))", String.GetUID (p.value)); END GenLiteral; PROCEDURE Split (e: Expr.T; VAR value: String.T): BOOLEAN = BEGIN TYPECASE e OF | NULL => RETURN FALSE; | P(p) => value := p.value; RETURN TRUE; ELSE RETURN FALSE; END; END Split; PROCEDURE Cat (a, b: Expr.T; VAR c: Expr.T): BOOLEAN = VAR sa, sb: String.T; BEGIN TYPECASE a OF | NULL => RETURN FALSE; | P(p) => sa := p.value; ELSE RETURN FALSE; END; TYPECASE b OF | NULL => RETURN FALSE; | P(p) => sb := p.value; ELSE RETURN FALSE; END; c := New (String.Concat (sa, sb)); RETURN TRUE; END Cat; PROCEDURE FPrinter (p: P; <*UNUSED*> map: Type.FPMap; wr: MBuf.T) = BEGIN MBuf.PutText (wr, "\""); String.Put (wr, p.value); MBuf.PutText (wr, "\""); END FPrinter; PROCEDURE IsZeroes (<*UNUSED*>p: P): BOOLEAN = BEGIN RETURN FALSE; END IsZeroes; BEGIN END TextExpr.