comments in symbol files, viewable by showdef browser.

This commit is contained in:
Norayr Chilingarian 2025-06-24 17:44:19 +04:00
parent 2f1ce08aff
commit dac6504f12
6 changed files with 348 additions and 97 deletions

View file

@ -8,6 +8,7 @@ MODULE OPM; (* RC 6.3.89 / 28.6.89, J.Templ 10.7.89 / 22.7.96 *)
CONST CONST
OptionChar* = "-"; OptionChar* = "-";
MaxCommentLen* = 256;
(* compiler option flag bits; don't change the encoding *) (* compiler option flag bits; don't change the encoding *)
inxchk* = 0; (* index check on *) inxchk* = 0; (* index check on *)
@ -76,15 +77,16 @@ MODULE OPM; (* RC 6.3.89 / 28.6.89, J.Templ 10.7.89 / 22.7.96 *)
BFext = ".c"; (* body file extension *) BFext = ".c"; (* body file extension *)
HFext = ".h"; (* header file extension *) HFext = ".h"; (* header file extension *)
SFtag = 0F7X; (* symbol file tag *) SFtag = 0F7X; (* symbol file tag *)
SFver = 083X; (* symbol file version. Increment if symbol file format is changed. *) SFver = 084X; (* symbol file version. Increment if symbol file format is changed. *)
TYPE TYPE
FileName = ARRAY 32 OF CHAR; FileName = ARRAY 32 OF CHAR;
VAR VAR
currentComment: ARRAY MaxCommentLen OF CHAR;
hasComment: BOOLEAN;
SourceFileName : ARRAY 256 OF CHAR; SourceFileName : ARRAY 256 OF CHAR;
GlobalModel, Model*: ARRAY 10 OF CHAR; (* 2: S8/I16/L32, C: S16/I32/L64, V:S8/I32/L64 *) GlobalModel, Model*: ARRAY 10 OF CHAR; (* 2: S8/I16/L32, C: S16/I32/L64, V:S8/I32/L64 *)
@ -150,6 +152,33 @@ MODULE OPM; (* RC 6.3.89 / 28.6.89, J.Templ 10.7.89 / 22.7.96 *)
LogW("."); LogW(".");
END LogCompiling; END LogCompiling;
(* for exported comments *)
PROCEDURE StoreComment*(text: ARRAY OF CHAR);
VAR i: INTEGER;
BEGIN
i := 0;
WHILE (i < MaxCommentLen - 1) & (text[i] # 0X) DO
currentComment[i] := text[i]; INC(i)
END;
currentComment[i] := 0X;
hasComment := TRUE;
END StoreComment;
PROCEDURE GetComment*(VAR text: ARRAY OF CHAR);
VAR i: INTEGER;
BEGIN
IF hasComment THEN
i := 0;
WHILE (i < LEN(text)) & (i < MaxCommentLen) & (currentComment[i] # 0X) DO
text[i] := currentComment[i]; INC(i)
END;
text[i] := 0X;
hasComment := FALSE
ELSE
text[0] := 0X
END;
END GetComment;
(* Integer size support *) (* Integer size support *)
@ -830,4 +859,7 @@ BEGIN
MinReal := -MaxReal; MinReal := -MaxReal;
MinLReal := -MaxLReal; MinLReal := -MaxLReal;
FindInstallDir; FindInstallDir;
hasComment := FALSE;
currentComment[0] := 0X;
END OPM. END OPM.

View file

@ -190,22 +190,92 @@ MODULE OPS; (* NW, RC 6.3.89 / 18.10.92 *) (* object model 3.6.92 *)
PROCEDURE Get*(VAR sym: SHORTINT); PROCEDURE Get*(VAR sym: SHORTINT);
VAR s: SHORTINT; VAR s: SHORTINT;
PROCEDURE Comment; (* do not read after end of file *) PROCEDURE Comment;
BEGIN OPM.Get(ch); VAR
LOOP isExported: BOOLEAN;
LOOP commentText: ARRAY OPM.MaxCommentLen OF CHAR;
WHILE ch = "(" DO OPM.Get(ch); i: INTEGER;
IF ch = "*" THEN Comment END nestLevel: INTEGER;
END ; prevCh, nextCh: CHAR;
IF ch = "*" THEN OPM.Get(ch); EXIT END ; BEGIN
IF ch = OPM.Eot THEN EXIT END ; FOR i := 0 TO LEN(commentText) - 1 DO
OPM.Get(ch) commentText[i] := 0X
END ; END;
IF ch = ")" THEN OPM.Get(ch); EXIT END ;
IF ch = OPM.Eot THEN err(5); EXIT END isExported := FALSE;
END i := 0;
nestLevel := 1;
prevCh := 0X;
OPM.Get(ch);
IF ch = "*" THEN
isExported := TRUE;
OPM.Get(ch);
IF ch = ")" THEN
(* Empty exported comment (**), handle and return *)
commentText[0] := 0X;
OPM.StoreComment(commentText);
OPM.Get(ch); (* consume character after closing comment *)
RETURN
END
END;
WHILE (nestLevel > 0) & (ch # OPM.Eot) DO
IF (prevCh = "(") & (ch = "*") THEN
INC(nestLevel);
prevCh := 0X
ELSIF (prevCh = "*") & (ch = ")") THEN
DEC(nestLevel);
IF nestLevel = 0 THEN
OPM.Get(ch); (* move past ')' *)
ELSE
prevCh := 0X
END
ELSE
IF isExported & (nestLevel = 1) & (prevCh # 0X) THEN
IF i < OPM.MaxCommentLen - 1 THEN
commentText[i] := prevCh; INC(i)
END
END;
prevCh := ch
END;
IF nestLevel > 0 THEN OPM.Get(ch) END
END;
IF ch = OPM.Eot THEN
err(5)
END;
(*
IF isExported & (nestLevel = 0) & (prevCh # 0X) & (prevCh # "*") & (i < OPM.MaxCommentLen - 2) THEN
commentText[i] := prevCh;
INC(i)
END;
*)
IF isExported & (nestLevel = 0) & (prevCh # 0X) & (prevCh # "*") THEN
IF i < OPM.MaxCommentLen - 1 THEN
commentText[i] := prevCh;
INC(i)
ELSE
OPM.LogWStr("Truncating final comment character"); OPM.LogWLn
END
END;
IF isExported THEN
IF i >= OPM.MaxCommentLen THEN
OPM.LogWStr("Warning: commentText overflow"); OPM.LogWLn;
i := OPM.MaxCommentLen - 1
END;
commentText[i] := 0X;
OPM.StoreComment(commentText)
END;
END Comment; END Comment;
BEGIN BEGIN
OPM.errpos := OPM.curpos-1; OPM.errpos := OPM.curpos-1;
WHILE ch <= " " DO (*ignore control characters*) WHILE ch <= " " DO (*ignore control characters*)

View file

@ -46,7 +46,8 @@ TYPE
typ*: Struct; typ*: Struct;
conval*: Const; conval*: Const;
adr*, linkadr*: LONGINT; adr*, linkadr*: LONGINT;
x*: INTEGER (* linkadr and x can be freely used by the backend *) x*: INTEGER; (* linkadr and x can be freely used by the backend *)
comment*: ConstExt;
END; END;
CONST CONST
@ -178,6 +179,7 @@ CONST
Shdptr* = 27; Shdpro* = 28; Stpro* = 29; Shdtpro* = 30; Sxpro* = 31; Shdptr* = 27; Shdpro* = 28; Stpro* = 29; Shdtpro* = 30; Sxpro* = 31;
Sipro* = 32; Scpro* = 33; Sstruct* = 34; Ssys* = 35; Sptr* = 36; Sipro* = 32; Scpro* = 33; Sstruct* = 34; Ssys* = 35; Sptr* = 36;
Sarr* = 37; Sdarr* = 38; Srec* = 39; Spro* = 40; Slink* = 37; Sarr* = 37; Sdarr* = 38; Srec* = 39; Spro* = 40; Slink* = 37;
Scomment* = 41;
TYPE TYPE
ImpCtxt = RECORD ImpCtxt = RECORD
@ -367,7 +369,15 @@ END NewConst;
PROCEDURE NewObj*(): Object; PROCEDURE NewObj*(): Object;
VAR obj: Object; VAR obj: Object;
BEGIN NEW(obj); RETURN obj BEGIN
NEW(obj);
(* lets fully init pointers *)
obj^.typ := NIL;
obj^.conval := NIL;
obj^.comment := NIL;
obj^.name := "";
RETURN obj
END NewObj; END NewObj;
PROCEDURE NewStr*(form, comp: SHORTINT): Struct; PROCEDURE NewStr*(form, comp: SHORTINT): Struct;
@ -468,8 +478,16 @@ BEGIN
END FindField; END FindField;
PROCEDURE Insert*(VAR name: OPS.Name; VAR obj: Object); PROCEDURE Insert*(VAR name: OPS.Name; VAR obj: Object);
VAR ob0, ob1: Object; left: BOOLEAN; mnolev: SHORTINT; VAR
BEGIN ob0 := topScope; ob1 := ob0^.right; left := FALSE; ob0, ob1: Object;
left: BOOLEAN;
mnolev: SHORTINT;
commentText: ARRAY OPM.MaxCommentLen OF CHAR;
j: INTEGER;
BEGIN
ob0 := topScope;
ob1 := ob0^.right;
left := FALSE;
LOOP LOOP
IF ob1 # NIL THEN IF ob1 # NIL THEN
IF name < ob1^.name THEN ob0 := ob1; ob1 := ob0^.left; left := TRUE IF name < ob1^.name THEN ob0 := ob1; ob1 := ob0^.left; left := TRUE
@ -480,13 +498,24 @@ BEGIN ob0 := topScope; ob1 := ob0^.right; left := FALSE;
IF left THEN ob0^.left := ob1 ELSE ob0^.right := ob1 END; IF left THEN ob0^.left := ob1 ELSE ob0^.right := ob1 END;
ob1^.left := NIL; ob1^.right := NIL; COPY(name, ob1^.name); ob1^.left := NIL; ob1^.right := NIL; COPY(name, ob1^.name);
mnolev := topScope^.mnolev; ob1^.mnolev := mnolev; mnolev := topScope^.mnolev; ob1^.mnolev := mnolev;
(* Attach pending comment *)
OPM.GetComment(commentText);
IF commentText[0] # 0X THEN
NEW(ob1^.comment);
(*COPY(commentText, ob1^.comment^);*)
j := 0;
WHILE (j < OPM.MaxCommentLen - 1) & (commentText[j] # 0X) DO
ob1^.comment^[j] := commentText[j];
INC(j)
END;
ob1^.comment^[j] := 0X;
END;
EXIT EXIT
END END
END; END;
obj := ob1 obj := ob1
END Insert; END Insert;
(*-------------------------- Fingerprinting --------------------------*) (*-------------------------- Fingerprinting --------------------------*)
(* Fingerprints prevent structural type equivalence. *) (* Fingerprints prevent structural type equivalence. *)
@ -791,13 +820,25 @@ PROCEDURE InSign(mno: SHORTINT; VAR res: Struct; VAR par: Object);
VAR last, new: Object; tag: LONGINT; VAR last, new: Object; tag: LONGINT;
BEGIN BEGIN
InStruct(res); InStruct(res);
tag := OPM.SymRInt(); last := NIL; tag := OPM.SymRInt();
last := NIL;
WHILE tag # Send DO WHILE tag # Send DO
new := NewObj(); new^.mnolev := -mno;
(* Add bounds checking *)
IF (tag < 0) OR (tag > 100) THEN
OPM.LogWStr("ERROR: Invalid tag value in InSign: "); OPM.LogWNum(tag, 0); OPM.LogWLn;
OPM.err(155); (* symbol file corrupted *)
RETURN
END;
new := NewObj();
new^.mnolev := -mno;
IF last = NIL THEN par := new ELSE last^.link := new END; IF last = NIL THEN par := new ELSE last^.link := new END;
IF tag = Svalpar THEN new^.mode := Var ELSE new^.mode := VarPar END; IF tag = Svalpar THEN new^.mode := Var ELSE new^.mode := VarPar END;
InStruct(new^.typ); new^.adr := OPM.SymRInt(); InName(new^.name); InStruct(new^.typ);
last := new; tag := OPM.SymRInt() new^.adr := OPM.SymRInt(); InName(new^.name);
last := new;
tag := OPM.SymRInt();
END END
END InSign; END InSign;
@ -973,11 +1014,46 @@ BEGIN
END END
END InStruct; END InStruct;
PROCEDURE InObj(mno: SHORTINT): Object; (* first number in impCtxt.nextTag *) PROCEDURE InObj(mno: SHORTINT): Object; (* first number in impCtxt.nextTag *)
VAR i, s: INTEGER; ch: CHAR; obj, old: Object; typ: Struct; VAR i, s: INTEGER; ch: CHAR; obj, old: Object; typ: Struct;
tag: LONGINT; ext: ConstExt; tag: LONGINT; ext: ConstExt;
commentText: OPS.Name;
hasComment : BOOLEAN;
j: INTEGER;
len: LONGINT;
BEGIN BEGIN
tag := impCtxt.nextTag; tag := impCtxt.nextTag;
hasComment := FALSE;
(* checking for comment first, but not processing it yet *)
WHILE tag = Scomment DO (* Handle multiple consecutive comments *)
len := OPM.SymRInt(); (* read length *)
(* Ensure length is within bounds *)
IF len < 0 THEN len := 0 END;
IF len > OPS.MaxStrLen - 1 THEN len := OPS.MaxStrLen - 1 END;
i := 0;
WHILE i < len DO
OPM.SymRCh(commentText[i]); INC(i)
END;
commentText[i] := 0X;
hasComment := TRUE; (* Only keep the last comment if there are multiple *)
tag := OPM.SymRInt(); (* continue stream *)
END;
(* Now tag should be a valid object tag *)
impCtxt.nextTag := tag;
(* Validate tag value *)
IF (tag < 0) OR (tag > 50) THEN
OPM.LogWStr("ERROR: Invalid tag in InObj: "); OPM.LogWNum(tag, 0); OPM.LogWLn;
OPM.err(155); (* Symbol file error *)
RETURN NIL
END;
IF tag = Stype THEN IF tag = Stype THEN
InStruct(typ); obj := typ^.strobj; InStruct(typ); obj := typ^.strobj;
IF ~impCtxt.self THEN obj^.vis := external END (* type name visible now, obj^.fprint already done *) IF ~impCtxt.self THEN obj^.vis := external END (* type name visible now, obj^.fprint already done *)
@ -986,7 +1062,7 @@ BEGIN
IF tag <= Pointer THEN (* Constant *) IF tag <= Pointer THEN (* Constant *)
obj^.mode := Con; obj^.conval := NewConst(); InConstant(tag, obj^.conval); obj^.mode := Con; obj^.conval := NewConst(); InConstant(tag, obj^.conval);
obj^.typ := InTyp(tag) obj^.typ := InTyp(tag)
ELSIF tag >= Sxpro THEN ELSIF (tag >= Sxpro) & (tag <= Scpro) THEN (* Procedure tags *)
obj^.conval := NewConst(); obj^.conval := NewConst();
obj^.conval^.intval := -1; obj^.conval^.intval := -1;
InSign(mno, obj^.typ, obj^.link); InSign(mno, obj^.typ, obj^.link);
@ -998,16 +1074,33 @@ BEGIN
s := SHORT(OPM.SymRInt()); ext^[0] := CHR(s); i := 1; s := SHORT(OPM.SymRInt()); ext^[0] := CHR(s); i := 1;
WHILE i <= s DO OPM.SymRCh(ext^[i]); INC(i) END WHILE i <= s DO OPM.SymRCh(ext^[i]); INC(i) END
ELSE OPM.LogWStr("unhandled case at InObj, tag = "); OPM.LogWNum(tag, 0); OPM.LogWLn; ELSE OPM.LogWStr("unhandled case at InObj, tag = "); OPM.LogWNum(tag, 0); OPM.LogWLn;
OPM.err(155); RETURN NIL
END END
ELSIF tag = Salias THEN ELSIF tag = Salias THEN
obj^.mode := Typ; InStruct(obj^.typ) obj^.mode := Typ; InStruct(obj^.typ)
ELSE ELSIF (tag = Svar) OR (tag = Srvar) THEN
obj^.mode := Var; obj^.mode := Var;
IF tag = Srvar THEN obj^.vis := externalR END; IF tag = Srvar THEN obj^.vis := externalR END;
InStruct(obj^.typ) InStruct(obj^.typ)
ELSE
OPM.LogWStr("ERROR: Unexpected tag in InObj: "); OPM.LogWNum(tag, 0); OPM.LogWLn;
OPM.err(155); (* Symbol file error *)
RETURN NIL
END; END;
InName(obj^.name) InName(obj^.name)
END; END;
(* attaching exported comment after the object was created *)
IF hasComment & (obj # NIL) THEN
NEW(obj^.comment);
j := 0;
WHILE (j < OPM.MaxCommentLen - 1) & (j < len) & (commentText[j] # 0X) DO
obj^.comment^[j] := commentText[j];
INC(j)
END;
obj^.comment^[j] := 0X;
END;
FPrintObj(obj); FPrintObj(obj);
IF (obj^.mode = Var) & ((obj^.typ^.strobj = NIL) OR (obj^.typ^.strobj^.name = "")) THEN IF (obj^.mode = Var) & ((obj^.typ^.strobj = NIL) OR (obj^.typ^.strobj^.name = "")) THEN
(* compute a global fingerprint to avoid structural type equivalence for anonymous types *) (* compute a global fingerprint to avoid structural type equivalence for anonymous types *)
@ -1040,6 +1133,8 @@ BEGIN
RETURN obj RETURN obj
END InObj; END InObj;
PROCEDURE Import*(aliasName: OPS.Name; VAR name: OPS.Name; VAR done: BOOLEAN); PROCEDURE Import*(aliasName: OPS.Name; VAR name: OPS.Name; VAR done: BOOLEAN);
VAR obj: Object; mno: SHORTINT; (* done used in Browser *) VAR obj: Object; mno: SHORTINT; (* done used in Browser *)
BEGIN BEGIN
@ -1226,45 +1321,71 @@ END Import;
END END
END OutConstant; END OutConstant;
PROCEDURE OutObj(obj: Object); PROCEDURE OutTruncatedName(text: ARRAY OF CHAR);
VAR i, j: INTEGER; ext: ConstExt; VAR i: INTEGER;
BEGIN BEGIN
IF obj # NIL THEN i := 0;
OutObj(obj^.left); WHILE (i < OPS.MaxStrLen - 1) & (text[i] # 0X) DO
IF obj^.mode IN {Con, Typ, Var, LProc, XProc, CProc, IProc} THEN OPM.SymWCh(text[i]); INC(i)
IF obj^.history = removed THEN FPrintErr(obj, 250) END;
ELSIF obj^.vis # internal THEN OPM.SymWCh(0X)
CASE obj^.history OF END OutTruncatedName;
| inserted: FPrintErr(obj, 253)
| same: (* ok *)
| pbmodified: FPrintErr(obj, 252) PROCEDURE OutObj(obj: Object);
| pvmodified: FPrintErr(obj, 251) VAR i, j: INTEGER; ext: ConstExt;
ELSE OPM.LogWStr("unhandled case at OutObj, obj^.history = "); OPM.LogWNum(obj^.history, 0); OPM.LogWLn; k, l: INTEGER;
END; BEGIN
CASE obj^.mode OF IF obj # NIL THEN
| Con: OutConstant(obj); OutName(obj^.name) OutObj(obj^.left);
| Typ: IF obj^.typ^.strobj = obj THEN OPM.SymWInt(Stype); OutStr(obj^.typ) IF obj^.mode IN {Con, Typ, Var, LProc, XProc, CProc, IProc} THEN
ELSE OPM.SymWInt(Salias); OutStr(obj^.typ); OutName(obj^.name) (* Write comment BEFORE the object *)
END IF obj^.comment # NIL THEN
| Var: IF obj^.vis = externalR THEN OPM.SymWInt(Srvar) ELSE OPM.SymWInt(Svar) END; OPM.SymWInt(Scomment);
OutStr(obj^.typ); OutName(obj^.name); (* Calculate actual length of comment text *)
IF (obj^.typ^.strobj = NIL) OR (obj^.typ^.strobj^.name = "") THEN k := 0;
(* compute fingerprint to avoid structural type equivalence *) WHILE (k < OPM.MaxCommentLen - 1) & (obj^.comment^[k] # 0X) DO INC(k) END;
OPM.FPrint(expCtxt.reffp, obj^.typ^.ref) OPM.SymWInt(k); (* length prefix *)
END (* Write comment data as individual characters *)
| XProc: OPM.SymWInt(Sxpro); OutSign(obj^.typ, obj^.link); OutName(obj^.name) l := 0;
| IProc: OPM.SymWInt(Sipro); OutSign(obj^.typ, obj^.link); OutName(obj^.name) WHILE l < k DO
| CProc: OPM.SymWInt(Scpro); OutSign(obj^.typ, obj^.link); ext := obj^.conval^.ext; OPM.SymWCh(obj^.comment^[l]); INC(l)
j := ORD(ext^[0]); i := 1; OPM.SymWInt(j);
WHILE i <= j DO OPM.SymWCh(ext^[i]); INC(i) END;
OutName(obj^.name)
ELSE OPM.LogWStr("unhandled case at OutObj, obj.mode = "); OPM.LogWNum(obj.mode, 0); OPM.LogWLn;
END
END END
END; END;
OutObj(obj^.right)
END IF obj^.history = removed THEN FPrintErr(obj, 250)
END OutObj; ELSIF obj^.vis # internal THEN
CASE obj^.history OF
| inserted: FPrintErr(obj, 253)
| same: (* ok *)
| pbmodified: FPrintErr(obj, 252)
| pvmodified: FPrintErr(obj, 251)
ELSE OPM.LogWStr("unhandled case at OutObj, obj^.history = "); OPM.LogWNum(obj^.history, 0); OPM.LogWLn;
END;
CASE obj^.mode OF
| Con: OutConstant(obj); OutName(obj^.name)
| Typ: IF obj^.typ^.strobj = obj THEN OPM.SymWInt(Stype); OutStr(obj^.typ)
ELSE OPM.SymWInt(Salias); OutStr(obj^.typ); OutName(obj^.name)
END
| Var: IF obj^.vis = externalR THEN OPM.SymWInt(Srvar) ELSE OPM.SymWInt(Svar) END;
OutStr(obj^.typ); OutName(obj^.name);
IF (obj^.typ^.strobj = NIL) OR (obj^.typ^.strobj^.name = "") THEN
(* compute fingerprint to avoid structural type equivalence *)
OPM.FPrint(expCtxt.reffp, obj^.typ^.ref)
END
| XProc: OPM.SymWInt(Sxpro); OutSign(obj^.typ, obj^.link); OutName(obj^.name)
| IProc: OPM.SymWInt(Sipro); OutSign(obj^.typ, obj^.link); OutName(obj^.name)
| CProc: OPM.SymWInt(Scpro); OutSign(obj^.typ, obj^.link); ext := obj^.conval^.ext;
j := ORD(ext^[0]); i := 1; OPM.SymWInt(j);
WHILE i <= j DO OPM.SymWCh(ext^[i]); INC(i) END;
OutName(obj^.name)
ELSE OPM.LogWStr("unhandled case at OutObj, obj.mode = "); OPM.LogWNum(obj.mode, 0); OPM.LogWLn;
END
END
END;
OutObj(obj^.right)
END
END OutObj;
PROCEDURE Export*(VAR ext, new: BOOLEAN); PROCEDURE Export*(VAR ext, new: BOOLEAN);
VAR i: INTEGER; nofmod: SHORTINT; done: BOOLEAN; VAR i: INTEGER; nofmod: SHORTINT; done: BOOLEAN;

View file

@ -1,47 +1,47 @@
(* $Id: IntStr.Mod,v 1.4 1999/09/02 13:07:47 acken Exp $ *) (* $Id: IntStr.Mod,v 1.4 1999/09/02 13:07:47 acken Exp $ *)
MODULE oocIntStr; MODULE oocIntStr;
(* IntStr - Integer-number/string conversions. (* IntStr - Integer-number/string conversions.
Copyright (C) 1995 Michael Griebling Copyright (C) 1995 Michael Griebling
This module is free software; you can redistribute it and/or modify This module is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2 of the published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version. License, or (at your option) any later version.
This module is distributed in the hope that it will be useful, This module is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write to the Free Software License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*) *)
IMPORT IMPORT
Conv := oocConvTypes, IntConv := oocIntConv; Conv := oocConvTypes, IntConv := oocIntConv;
TYPE TYPE
ConvResults*= Conv.ConvResults; ConvResults*= Conv.ConvResults;
(* possible values: strAllRight, strOutOfRange, strWrongFormat, strEmpty *) (** possible values: strAllRight, strOutOfRange, strWrongFormat, strEmpty *)
CONST CONST
strAllRight*=Conv.strAllRight; strAllRight*=Conv.strAllRight;
(* the string format is correct for the corresponding conversion *) (** the string format is correct for the corresponding conversion *)
strOutOfRange*=Conv.strOutOfRange; strOutOfRange*=Conv.strOutOfRange;
(* the string is well-formed but the value cannot be represented *) (** the string is well-formed but the value cannot be represented *)
strWrongFormat*=Conv.strWrongFormat; strWrongFormat*=Conv.strWrongFormat;
(* the string is in the wrong format for the conversion *) (** the string is in the wrong format for the conversion *)
strEmpty*=Conv.strEmpty; strEmpty*=Conv.strEmpty;
(* the given string is empty *) (** the given string is empty *)
(* the string form of a signed whole number is (** the string form of a signed whole number is
["+" | "-"] decimal_digit {decimal_digit} ["+" | "-"] decimal_digit {decimal_digit}
*) *)
PROCEDURE StrToInt*(str: ARRAY OF CHAR; VAR int: LONGINT; VAR res: ConvResults); PROCEDURE StrToInt*(str: ARRAY OF CHAR; VAR int: LONGINT; VAR res: ConvResults);
(* Ignores any leading spaces in `str'. If the subsequent characters in `str' (** Ignores any leading spaces in `str'. If the subsequent characters in `str'
are in the format of a signed whole number, assigns a corresponding value to are in the format of a signed whole number, assigns a corresponding value to
`int'. Assigns a value indicating the format of `str' to `res'. *) `int'. Assigns a value indicating the format of `str' to `res'. *)
BEGIN BEGIN
@ -53,7 +53,7 @@ END StrToInt;
PROCEDURE Reverse (VAR str : ARRAY OF CHAR; start, end : INTEGER); PROCEDURE Reverse (VAR str : ARRAY OF CHAR; start, end : INTEGER);
(* Reverses order of characters in the interval [start..end]. *) (** Reverses order of characters in the interval [start..end]. *)
VAR VAR
h : CHAR; h : CHAR;
BEGIN BEGIN
@ -65,7 +65,7 @@ END Reverse;
PROCEDURE IntToStr*(int: LONGINT; VAR str: ARRAY OF CHAR); PROCEDURE IntToStr*(int: LONGINT; VAR str: ARRAY OF CHAR);
(* Converts the value of `int' to string form and copies the possibly truncated (** Converts the value of `int' to string form and copies the possibly truncated
result to `str'. *) result to `str'. *)
CONST CONST
maxLength = 11; (* maximum number of digits representing a LONGINT value *) maxLength = 11; (* maximum number of digits representing a LONGINT value *)
@ -92,9 +92,9 @@ BEGIN
b[e] := 0X; b[e] := 0X;
Reverse(b, s, e-1) Reverse(b, s, e-1)
END; END;
COPY(b, str) (* truncate output if necessary *) COPY(b, str) (* truncate output if necessary *)
END IntToStr; END IntToStr;
END oocIntStr. END oocIntStr.

View file

@ -1,4 +1,7 @@
MODULE Out; (* DCW Brown. 2016-09-27 *) MODULE Out; (* DCW Brown. 2016-09-27 *)
(** Module Out provides a set of basic routines
for formatted output of characters, numbers, and strings.
It assumes a standard output stream to which the symbols are written. *)
IMPORT SYSTEM, Platform, Heap; IMPORT SYSTEM, Platform, Heap;
@ -16,11 +19,11 @@ BEGIN
IF in > 0 THEN error := Platform.Write(Platform.StdOut, SYSTEM.ADR(buf), in) END; IF in > 0 THEN error := Platform.Write(Platform.StdOut, SYSTEM.ADR(buf), in) END;
in := 0; in := 0;
END Flush; END Flush;
(** Initializes the output stream. In this library does nothing, safe to never use. *)
PROCEDURE Open*; PROCEDURE Open*;
BEGIN BEGIN
END Open; END Open;
(** Writes the character to the end of the output stream. *)
PROCEDURE Char*(ch: CHAR); PROCEDURE Char*(ch: CHAR);
BEGIN BEGIN
IF in >= LEN(buf) THEN Flush END; IF in >= LEN(buf) THEN Flush END;
@ -32,7 +35,7 @@ PROCEDURE Length(VAR s: ARRAY OF CHAR): LONGINT;
VAR l: LONGINT; VAR l: LONGINT;
BEGIN l := 0; WHILE (l < LEN(s)) & (s[l] # 0X) DO INC(l) END; RETURN l BEGIN l := 0; WHILE (l < LEN(s)) & (s[l] # 0X) DO INC(l) END; RETURN l
END Length; END Length;
(** Writes the null-terminated character sequence str to the end of the output stream (without 0X). *)
PROCEDURE String*(str: ARRAY OF CHAR); PROCEDURE String*(str: ARRAY OF CHAR);
VAR l: LONGINT; error: Platform.ErrorCode; VAR l: LONGINT; error: Platform.ErrorCode;
BEGIN BEGIN
@ -46,7 +49,10 @@ BEGIN
END END
END String; END String;
(** Writes the integer number x to the end of the output stream.
If the textual representation of x requires m characters,
x is right adjusted in a field of Max(n, m) characters
padded with blanks at the left end. a plus sign is not written. *)
PROCEDURE Int*(x, n: HUGEINT); PROCEDURE Int*(x, n: HUGEINT);
CONST zero = ORD('0'); CONST zero = ORD('0');
VAR s: ARRAY 22 OF CHAR; i: INTEGER; negative: BOOLEAN; VAR s: ARRAY 22 OF CHAR; i: INTEGER; negative: BOOLEAN;
@ -82,7 +88,7 @@ BEGIN
ELSE Char(CHR((x MOD 16) - 10 + ORD('A'))) END ELSE Char(CHR((x MOD 16) - 10 + ORD('A'))) END
END END
END Hex; END Hex;
(** Writes an end-of-line symbol to the end of the output stream *)
PROCEDURE Ln*; PROCEDURE Ln*;
BEGIN String(Platform.NL); Flush; BEGIN String(Platform.NL); Flush;
END Ln; END Ln;
@ -117,14 +123,15 @@ END Ten;
PROCEDURE -Entier64(x: LONGREAL): SYSTEM.INT64 "(INT64)(x)"; PROCEDURE -Entier64(x: LONGREAL): SYSTEM.INT64 "(INT64)(x)";
PROCEDURE RealP(x: LONGREAL; n: INTEGER; long: BOOLEAN); (** RealP(x, n) writes the long real number x to the end of the output stream using an
(* RealP(x, n) writes the long real number x to the end of the output stream using an
exponential form. If the textual representation of x requires m characters (including a exponential form. If the textual representation of x requires m characters (including a
three-digit signed exponent), x is right adjusted in a eld of Max(n, m) characters padded three-digit signed exponent), x is right adjusted in a eld of Max(n, m) characters padded
with blanks at the left end. A plus sign of the mantissa is not written. with blanks at the left end. A plus sign of the mantissa is not written.
LONGREAL is 1/sign, 11/exponent, 52/significand *) LONGREAL is 1/sign, 11/exponent, 52/significand *)
PROCEDURE RealP(x: LONGREAL; n: INTEGER; long: BOOLEAN);
VAR VAR
e: INTEGER; (* Exponent field *) e: INTEGER; (* Exponent field *)
f: HUGEINT; (* Fraction field *) f: HUGEINT; (* Fraction field *)
@ -212,11 +219,18 @@ BEGIN
WHILE i < LEN(s) DO Char(s[i]); INC(i) END WHILE i < LEN(s) DO Char(s[i]); INC(i) END
END RealP; END RealP;
(** Writes the real number x to the end of the output stream using an exponential
form. If the textual representation of x requires m characters (including a
two-digit signed exponent), x is right adjusted in a field of Max(n, m) characters
padded with blanks at the left end. A plus sign of the mantissa is not written.*)
PROCEDURE Real*(x: REAL; n: INTEGER); PROCEDURE Real*(x: REAL; n: INTEGER);
BEGIN RealP(x, n, FALSE); BEGIN RealP(x, n, FALSE);
END Real; END Real;
(** Writes the long real number x to the end of the output stream using an exponential form.
If the textual representation of x requires m characters (including a three-digit
signed exponent), x is right adjusted in a field of Max(n, m) characters padded
with blanks at the left end. A plus sign of the mantissa is not written. *)
PROCEDURE LongReal*(x: LONGREAL; n: INTEGER); PROCEDURE LongReal*(x: LONGREAL; n: INTEGER);
BEGIN RealP(x, n, TRUE); BEGIN RealP(x, n, TRUE);
END LongReal; END LongReal;
@ -224,4 +238,10 @@ END LongReal;
BEGIN BEGIN
IsConsole := Platform.IsConsole(Platform.StdOut); IsConsole := Platform.IsConsole(Platform.StdOut);
in := 0 in := 0
(** This module originally was designed by Martin Reiser
for the book "Programming in Oberon".
the specification was proposed by H. Moessenbock *)
END Out. END Out.

View file

@ -63,6 +63,14 @@ MODULE BrowserCmd; (* RC 29.10.93 *) (* object model 4.12.93, command line ver
IF obj # NIL THEN IF obj # NIL THEN
Objects(obj^.left, mode); Objects(obj^.left, mode);
IF obj^.mode IN mode THEN IF obj^.mode IN mode THEN
(* Output comment if present *)
IF obj^.comment # NIL THEN
Indent(1);
Ws("(** ");
Ws(obj^.comment^);
Ws(" *)");
Wln
END;
CASE obj^.mode OF CASE obj^.mode OF
|OPT.Con: Indent(2); Ws(obj^.name); Ws(" = "); |OPT.Con: Indent(2); Ws(obj^.name); Ws(" = ");
CASE obj^.typ^.form OF CASE obj^.typ^.form OF