File: TFI3dImpl.mesa (Text File-In for 3d scenes)
Last edited by Bier on March 1, 1987 6:08:51 pm PST
Copyright © 1984 by Xerox Corporation. All rights reserved.
Contents: convenience functions for parsing low-level parts of a 3d fileout produced by fileout3d.mesa
DIRECTORY
AtomButtonsTypes, SVGraphics, Feedback, Imager, ImagerColor, IO, Matrix3d, Rope, SV2d, SV3d, SVArtwork, SVMappings, SVMatrix2d, SVModelTypes, SVPolygon3d, SVScene, SVSceneTypes, TFI3d, ViewerClasses;
TFI3dImpl:
CEDAR PROGRAM
IMPORTS SVGraphics, ImagerColor, IO, Matrix3d, SVArtwork, Feedback, SVMappings, SVMatrix2d, SVPolygon3d, SVScene, Rope
EXPORTS TFI3d =
BEGIN
Slice: TYPE = SVSceneTypes.Slice;
Color: TYPE = Imager.Color;
CoordSystem: TYPE = SVModelTypes.CoordSystem;
DrawStyle: TYPE = SVModelTypes.DrawStyle;
FeedbackData: TYPE = AtomButtonsTypes.FeedbackData;
FileCamera: TYPE = SVSceneTypes.FileCamera;
FrameBox: TYPE = REF FrameBoxObj;
FrameBoxObj: TYPE = SVModelTypes.FrameBoxObj;
Matrix3by3: TYPE = SV2d.Matrix3by3;
Matrix4by4: TYPE = SV3d.Matrix4by4;
OMap: TYPE = SVModelTypes.OMap;
Plane: TYPE = SV3d.Plane;
Point3d: TYPE = SV3d.Point3d;
Point2d: TYPE = SV2d.Point2d;
Projection: TYPE = SVModelTypes.Projection;
Scene: TYPE = SVSceneTypes.Scene;
Vector3d: TYPE = SV3d.Vector3d;
Viewer: TYPE = ViewerClasses.Viewer;
Material: TYPE = SVModelTypes.Material;
SMap: TYPE = SVModelTypes.SMap;
CharClass: TYPE = IO.CharClass;
{break, sepr, other}
FileinMatrix:
PUBLIC
PROC [f:
IO.
STREAM]
RETURNS [mat: Matrix4by4] = {
mat ← Matrix3d.Identity[];
ReadRope[f, "["];
ReadBlankAndRope[f, "["];
mat[1][1] ← ReadBlankAndReal[f];
FOR j:
NAT
IN[2..4]
DO
ReadBlankAndRope[f,","];
mat[1][j] ← ReadBlankAndReal[f];
ENDLOOP;
ReadBlank[f];
ReadBlankAndRope[f, "]"];
FOR i:
NAT
IN[2..3]
DO
ReadBlankAndRope[f, ","];
ReadBlankAndRope[f, "["];
mat[i][1] ← ReadBlankAndReal[f];
FOR j:
NAT
IN[2..4]
DO
ReadBlankAndRope[f, ","];
mat[i][j] ← ReadBlankAndReal[f];
ENDLOOP;
ReadBlankAndRope[f, "]"];
ENDLOOP;
ReadBlankAndRope[f, "]"];
}; -- end of FileinMatrix
FileinMatrix3by3:
PUBLIC
PROC [f:
IO.
STREAM]
RETURNS [mat: Matrix3by3] = {
mat ← SVMatrix2d.Identity[];
ReadRope[f, "["];
ReadBlankAndRope[f, "["];
mat[1][1] ← ReadBlankAndReal[f];
FOR j:
NAT
IN[2..3]
DO
ReadBlankAndRope[f,","];
mat[1][j] ← ReadBlankAndReal[f];
ENDLOOP;
ReadBlank[f];
ReadBlankAndRope[f, "]"];
ReadBlankAndRope[f, ","];
ReadBlankAndRope[f, "["];
mat[2][1] ← ReadBlankAndReal[f];
FOR j: NAT IN[2..3] DO
ReadBlankAndRope[f, ","];
mat[2][j] ← ReadBlankAndReal[f];
ENDLOOP;
ReadBlankAndRope[f, "]"];
ReadBlankAndRope[f, "]"];
}; -- end of FileinMatrix3by3
ReadRope:
PUBLIC
PROC [f:
IO.
STREAM, rope: Rope.
ROPE] = {
Removes the given rope from the top of the stream. Used to remove formatting words and phrases from 3d files. We are not interested in these strings but only in the data in between them.
Signals RopeNotOnTop if some other rope is on top.
c: CHAR;
endofstream: BOOL ← FALSE;
FOR i:
INT
IN[1..Rope.Length[rope]]
DO
c ←
IO.GetChar[f
! IO.EndOfStream => {endofstream ← TRUE; CONTINUE}];
IF endofstream
THEN
SIGNAL RopeNotOnTop [IO.GetIndex[f], NIL, rope];
IF
NOT c = Rope.Fetch[rope,i-1]
THEN
SIGNAL RopeNotOnTop [IO.GetIndex[f], Rope.FromChar[c], rope];
ENDLOOP;
};
RopeNotOnTop: PUBLIC SIGNAL [position: NAT, wasThere: Rope.ROPE, notThere: Rope.ROPE] = CODE;
ReadChar:
PUBLIC
PROC [f:
IO.
STREAM, c:
CHAR] = {
streamC: CHAR ← IO.GetChar[f];
IF NOT c = streamC THEN SIGNAL RopeNotOnTop[IO.GetIndex[f], Rope.FromChar[streamC], Rope.FromChar[c]];
};
ReadReturn:
PUBLIC
PROC [f:
IO.
STREAM] = {
Convenience function. Equivalent to ReadChar[f, IO.CR];
ReadChar[f, IO.CR];
};
WordBreakProc:
SAFE
PROC [char:
CHAR]
RETURNS [
IO.CharClass] =
CHECKED {
SELECT char
FROM
IO.TAB => RETURN [break];
IO.CR =>RETURN [break];
IO.SP => RETURN [break];
', => RETURN [break];
'] => RETURN [break];
') => RETURN [break];
ENDCASE => RETURN [other];
};
KeyWordBreakProc:
SAFE
PROC [char:
CHAR]
RETURNS [
IO.CharClass] =
CHECKED {
SELECT char
FROM
IO.CR =>RETURN [break];
': => RETURN [break];
ENDCASE => RETURN [other];
};
ReadWord:
PUBLIC
PROC [f:
IO.
STREAM]
RETURNS [word: Rope.
ROPE] = {
Reads a rope until <SPACE>, <CR>, <COMMA> or <TAB> are encountered. Used to read in a rope which is data. ie the name of a coordinate system from a 3d file.
[word,
----] ←
IO.GetTokenRope[f, WordBreakProc
!IO.EndOfStream => {word ← NIL; CONTINUE}];
};
ReadKeyWord:
PUBLIC
PROC [f:
IO.
STREAM]
RETURNS [keyWord: Rope.
ROPE, good:
BOOL] = {
Reads a rope until a ':' or <CR> are encountered. If CR is encountered first, then good is FALSE since ":" is expected after a keyword.
end: BOOL ← FALSE;
nextChar: Rope.ROPE;
[keyWord,
----] ←
IO.GetTokenRope[f, KeyWordBreakProc
!IO.EndOfStream => {end ← TRUE; CONTINUE}];
IF end THEN {good ← FALSE; keyWord ← NIL; RETURN};
[nextChar,
----] ←
IO.GetTokenRope[f, KeyWordBreakProc
!IO.EndOfStream => {end ← TRUE; CONTINUE}];
IF end THEN {good ← FALSE; RETURN};
good ← Rope.Equal[nextChar, ":", TRUE];
};
LineBreakProc:
SAFE
PROC [char:
CHAR]
RETURNS [
IO.CharClass] =
CHECKED {
SELECT char
FROM
IO.CR =>RETURN [break];
ENDCASE => RETURN [other];
};
ReadLine:
PUBLIC
PROC [f:
IO.
STREAM]
RETURNS [line: Rope.
ROPE] = {
Reads a rope UNTIL <CR> is encountered. Used to read Solidviews version rope
end: BOOL ← FALSE;
[line,
----] ←
IO.GetTokenRope[f, LineBreakProc
!IO.EndOfStream => {end ← TRUE; CONTINUE}];
IF end THEN {line ← NIL; RETURN};
[----, ----] ← IO.GetTokenRope[f, LineBreakProc]; -- remove <CR>
};
WhiteSpaceProc:
SAFE
PROC [char:
CHAR]
RETURNS [
IO.CharClass] = {
SELECT char
FROM
IO.TAB => RETURN [other];
IO.CR =>RETURN [other];
IO.SP => RETURN [other];
ENDCASE => RETURN [break];
};
ReadWhiteSpace:
PUBLIC
PROC [f:
IO.
STREAM] = {
Reads, <SPACE>'s, <CR>'s, and <TAB>'s until something else is encountered. Signals RopeNotOnTop if no white space characters are found.
whiteSpace: Rope.ROPE;
end: BOOL ← FALSE;
[whiteSpace,
----] ←
IO.GetTokenRope[f, WhiteSpaceProc
!IO.EndOfStream => {end ← TRUE; CONTINUE}];
IF end OR Rope.Size[whiteSpace] = 0 THEN SIGNAL RopeNotOnTop[IO.GetIndex[f], "null", "<whitespace>"];
};
ReadBlank:
PUBLIC
PROC [f:
IO.
STREAM] = {
Reads, <SPACE>'s, <CR>'s, and <TAB>'s until something else is encountered. Doesn't mind if no white space characters are found. Treats comments as white space.
[] ← IO.SkipWhitespace[f, TRUE];
};
ReadHorizontalBlank:
PUBLIC
PROC [f:
IO.
STREAM]
RETURNS [good:
BOOL] = {
Reads <SPACE>'s, and <TABS>'s until something else is encountered. Returns good = FALSE if a CR is encountered before anything else
whiteSpace: Rope.ROPE;
c: CHAR;
end: BOOL ← FALSE;
good ← TRUE;
[whiteSpace,
----] ←
IO.GetTokenRope[f, HorizontalBlankProc
!IO.EndOfStream => {end ← TRUE; CONTINUE}];
IF end THEN {good ← FALSE; RETURN};
c ← Rope.Fetch[whiteSpace, 0];
SELECT c
FROM
IO.CR => {good ← FALSE; RETURN};
IO.TAB, IO.SP => {good ← TRUE; RETURN};
ENDCASE => {good ← TRUE; IO.Backup[f, c]; RETURN};
};
HorizontalBlankProc:
SAFE
PROC [char:
CHAR]
RETURNS [CharClass] = {
SELECT char
FROM
IO.TAB, IO.SP => RETURN [other];
ENDCASE => RETURN [break];
};
ReadBlankAndRope:
PUBLIC
PROC [f:
IO.
STREAM, rope: Rope.
ROPE] = {
ReadBlank[f];
ReadRope[f, rope];
};
ReadBlankAndReal:
PUBLIC
PROC [f:
IO.
STREAM]
RETURNS [r:
REAL] = {
A convenience function. Equivalent to ReadBlank[f]; r ← ReadReal[f];
ReadBlank[f];
r ← ReadReal[f];
};
ReadBlankAndWord:
PUBLIC
PROC [f:
IO.
STREAM]
RETURNS [word: Rope.
ROPE] = {
A convenience function. Equivalent to ReadBlank[f]; word ← ReadWord[f];
ReadBlank[f];
word ← ReadWord[f];
};
ReadBlankAndNAT:
PUBLIC
PROC [f:
IO.
STREAM]
RETURNS [n:
NAT] = {
A convenience function. Equivalent to ReadBlank[f]; n ← ReadNAT[f];
ReadBlank[f];
n ← ReadNAT[f];
};
ReadPoint3d:
PUBLIC
PROC [f:
IO.
STREAM]
RETURNS [point3d: Point3d] = {
Assumes the next rope on the stream will be of the form "[<real1>,<real2>,<real3>]".
ReadRope[f, "["];
point3d[1] ← ReadBlankAndReal[f];
ReadRope[f, ","];
point3d[2] ← ReadBlankAndReal[f];
ReadRope[f, ","];
point3d[3] ← ReadBlankAndReal[f];
ReadRope[f, "]"];
};
ReadPoint2d:
PUBLIC
PROC [f:
IO.
STREAM]
RETURNS [point2d: Point2d] = {
Assumes the next rope on the stream will be of the form "[<real1>,<real2>]".
ReadRope[f, "["];
point2d[1] ← ReadBlankAndReal[f];
ReadRope[f, ","];
point2d[2] ← ReadBlankAndReal[f];
ReadRope[f, "]"];
};
ReadPoint2dAsPoint3d:
PUBLIC
PROC [f:
IO.
STREAM]
RETURNS [point3d: Point3d] = {
Assumes the next rope on the stream will be of the form "[<real1>,<real2>]". Fills in point3d[3] with zero.
ReadRope[f, "["];
point3d[1] ← ReadBlankAndReal[f];
ReadRope[f, ","];
point3d[2] ← ReadBlankAndReal[f];
point3d[3] ← 0;
ReadRope[f, "]"];
};
RealBreakProc:
SAFE
PROC [char:
CHAR]
RETURNS [
IO.CharClass] = {
SELECT char
FROM
'], ', => RETURN [break];
IO.CR =>RETURN [break];
IO.SP => RETURN [break];
ENDCASE => RETURN [other];
};
ReadReal:
PUBLIC
PROC [f:
IO.
STREAM]
RETURNS [r:
REAL] = {
Reads digits up to the next ], <CR>, <SPACE> or <COMMA>. Leaves these terminators on the stream.
realRope: Rope.ROPE;
end: BOOL ← FALSE;
[realRope,
----] ←
IO.GetTokenRope[f, RealBreakProc
!IO.EndOfStream => {end ← TRUE; CONTINUE}];
IF end THEN {r ← 0.0; RETURN};
IF Rope.Find[realRope, ".", 0, FALSE] = -1 THEN realRope ← Rope.Concat[realRope, ".0"];
r ← IO.GetReal[IO.RIS[realRope]];
};
NATBreakProc:
SAFE
PROC [char:
CHAR]
RETURNS [
IO.CharClass] = {
SELECT char
FROM
'], IO.CR, IO.SP, '., ', => RETURN [break];
ENDCASE => RETURN [other];
};
ReadNAT:
PUBLIC
PROC [f:
IO.
STREAM]
RETURNS [n:
NAT] = {
Reads digits up to the next ], <CR>, <SPACE>. Leaves these terminators on the stream.
end: BOOL ← FALSE;
intRope: Rope.ROPE;
[intRope,
----] ←
IO.GetTokenRope[f, NATBreakProc
!IO.EndOfStream => {end ← TRUE; CONTINUE}];
IF end THEN {n ← 1; RETURN};
n ← IO.GetInt[IO.RIS[intRope]];
};
BoolBreakProc:
SAFE
PROC [char:
CHAR]
RETURNS [
IO.CharClass] = {
SELECT char
FROM
'], IO.CR, IO.SP, '., ', => RETURN [break];
ENDCASE => RETURN [other];
};
ReadBool:
PUBLIC
PROC [f:
IO.
STREAM]
RETURNS [truth:
BOOL, good:
BOOL] = {
Tries to read TRUE or FALSE from the stream. If it encounters another word, good = FALSE;
end: BOOL ← FALSE;
boolRope: Rope.ROPE;
[boolRope,
----] ←
IO.GetTokenRope[f, BoolBreakProc
!IO.EndOfStream => {end ← TRUE; CONTINUE}];
IF end THEN {good ← FALSE; truth ← FALSE; RETURN};
good ← TRUE;
IF Rope.Equal[boolRope, "TRUE", TRUE] THEN truth ← TRUE
ELSE
IF Rope.Equal[boolRope, "FALSE",
TRUE]
THEN truth ←
FALSE
ELSE {truth ← FALSE; good ← FALSE};
};
ReadColor:
PUBLIC
PROC [f:
IO.
STREAM]
RETURNS [color: Color] = {
r, g, b: REAL;
ReadChar[f, '[];
r ← ReadBlankAndReal[f];
ReadChar[f, ',];
g ← ReadBlankAndReal[f];
ReadChar[f, ',];
b ← ReadBlankAndReal[f];
ReadChar[f, ']];
color ← ImagerColor.ColorFromRGB[[r, g, b]];
}; -- end of ReadColor
ReadSurface:
PUBLIC
PROC [f:
IO.
STREAM]
RETURNS [surface:
REF
ANY] = {
surfType: Rope.ROPE ← ReadBlankAndWord[f];
SELECT
TRUE
FROM
Rope.Equal[surfType, "tube",
FALSE] => {
radius, height: REAL;
ReadBlankAndRope[f, "[radius:"];
radius ← ReadBlankAndReal[f];
ReadBlankAndRope[f, ","];
ReadBlankAndRope[f, "height:"];
height ← ReadBlankAndReal[f];
ReadBlankAndRope[f, "]"];
surface ← SVMappings.CreateTube[radius, height];
};
Rope.Equal[surfType, "box",
FALSE] => {
boxSide: Vector3d;
ReadBlank[f];
boxSide ← ReadPoint3d[f];
surface ← SVMappings.CreateBox[boxSide[1], boxSide[2], boxSide[3]];
};
Rope.Equal[surfType, "NIL"] => {};
ENDCASE => ERROR;
}; -- end of ReadSurface
ReadMaterial:
PUBLIC
PROC [f:
IO.
STREAM]
RETURNS [material: Material] = {
matRope: Rope.ROPE ← ReadWord[f];
success: BOOL;
[material, success] ← SVArtwork.RopeToMaterial[matRope];
IF NOT success THEN ERROR;
};
ReadSMap:
PUBLIC
PROC [f:
IO.
STREAM]
RETURNS [sMap: SMap] = {
mapRope: Rope.ROPE ← ReadWord[f];
success: BOOL;
[sMap, success] ← SVArtwork.RopeToSMap[mapRope];
IF NOT success THEN ERROR;
};
ReadOMap:
PUBLIC
PROC [f:
IO.
STREAM]
RETURNS [oMap: OMap] = {
mapRope: Rope.ROPE ← ReadWord[f];
success: BOOL;
[oMap, success] ← SVArtwork.RopeToOMap[mapRope];
IF NOT success THEN ERROR;
};
ReadCamera:
PUBLIC
PROC [f:
IO.
STREAM, worldCS: CoordSystem, scene: Scene, version:
REAL]
RETURNS [fileCamera: FileCamera] = {
name: Rope.ROPE;
origin, focusPoint: Point3d;
slant, focalLength, resolution: REAL;
projection: Projection;
projectionRope: Rope.ROPE;
clippingPlanes: LIST OF Plane;
visibleAssemblies: LIST OF Rope.ROPE;
frame: FrameBox;
success: BOOL;
ReadBlankAndRope[f, "Camera:"];
name ← ReadBlankAndWord[f];
ReadBlankAndRope[f, "origin:"];
ReadBlank[f];
origin ← ReadPoint3d[f];
ReadBlankAndRope[f, "focusPoint:"];
ReadBlank[f];
focusPoint ← ReadPoint3d[f];
ReadBlankAndRope[f, "slant:"];
slant ← ReadBlankAndReal[f];
ReadBlankAndRope[f, "resolution:"];
resolution ← ReadBlankAndReal[f];
ReadBlankAndRope[f, "focalLength:"];
focalLength ← ReadBlankAndReal[f];
IF version > 5.1
THEN {
ReadBlankAndRope[f, "projection:"];
projectionRope ← ReadBlankAndWord[f];
[projection, success] ← SVGraphics.RopeToProjection[projectionRope];
IF NOT success THEN projection ← perspective;
}
ELSE projection ← perspective;
ReadBlankAndRope[f, "frame:"];
ReadBlank[f];
frame ← ReadFrame[f];
ReadBlankAndRope[f, "clippingPlanes:"];
clippingPlanes ← ReadClippingPlanes[f];
ReadBlankAndRope[f, "visibleAssemblies:"];
visibleAssemblies ← ReadListOfRope[f];
ReadBlank[f];
fileCamera ← SVScene.CreateFileCamera[name, origin, focusPoint, slant, resolution, focalLength, projection, frame, clippingPlanes, visibleAssemblies];
};
ReadClippingPlanes:
PUBLIC
PROC [f:
IO.
STREAM]
RETURNS [clippingPlanes:
LIST
OF Plane] = {
plane: Plane;
continue: BOOL;
clippingPlanes ← NIL;
continue ← ReadHorizontalBlank[f];
IF NOT continue THEN RETURN;
plane ← ReadPlane[f];
clippingPlanes ← AppendPlaneToList[plane, clippingPlanes];
WHILE
TRUE
DO
continue ← ReadHorizontalBlank[f];
IF NOT continue THEN RETURN;
ReadRope[f, ","];
ReadBlank[f];
plane ← ReadPlane[f];
clippingPlanes ← AppendPlaneToList[plane, clippingPlanes];
ENDLOOP;
};
AppendPlaneToList:
PROC [plane: Plane, list:
LIST
OF Plane]
RETURNS [
LIST
OF Plane] = {
A copy of List.Nconc1 for LIST OF Plane instead of LIST OF REF ANY
z: LIST OF Plane ← list;
IF z = NIL THEN RETURN[CONS[plane,NIL]];
UNTIL z.rest = NIL DO z ← z.rest; ENDLOOP;
z.rest ← CONS[plane,NIL];
RETURN[list];
};
ReadPlane:
PUBLIC
PROC [f:
IO.
STREAM]
RETURNS [plane: Plane] = {
A, B, C, D: REAL;
ReadBlankAndRope[f, "["];
A ← ReadBlankAndReal[f];
ReadBlankAndRope[f, ","];
B ← ReadBlankAndReal[f];
ReadBlankAndRope[f, ","];
C ← ReadBlankAndReal[f];
ReadBlankAndRope[f, ","];
D ← ReadBlankAndReal[f];
ReadBlankAndRope[f, "]"];
plane ← SVPolygon3d.PlaneFromCoefficients[A, B, C, D];
};
ReadStyle:
PUBLIC
PROC [f:
IO.
STREAM]
RETURNS [style: DrawStyle] = {
styleName: Rope.ROPE ← ReadBlankAndWord[f];
success: BOOL;
[style, success] ← SVGraphics.RopeToDrawStyle[styleName];
IF NOT success THEN style ← wire;
}; -- end of ReadStyle
ReadFrame:
PUBLIC
PROC [f:
IO.
STREAM]
RETURNS [frame: FrameBox] = {
success: BOOL;
point: Point2d;
frame ← NEW[FrameBoxObj];
ReadBlankAndRope[f, "["];
ReadBlank[f];
point ← ReadPoint2d[f];
frame.downLeft[1] ← point[1];
frame.upRight[2] ← point[2];
ReadBlankAndRope[f, ","];
ReadBlank[f];
point ← ReadPoint2d[f];
frame.upRight[1] ← point[1];
frame.downLeft[2] ← point[2];
ReadBlankAndRope[f, "fullScreen:"];
ReadBlank[f];
[frame.fullScreen, success] ← ReadBool[f];
IF NOT success THEN frame.fullScreen ← TRUE;
ReadBlankAndRope[f, "]"];
}; -- end of ReadFrame
RopesOnOneLineProc:
SAFE
PROC [char:
CHAR]
RETURNS [
IO.CharClass] =
CHECKED {
SELECT char
FROM
IO.CR =>RETURN [break];
IO.SP, IO.TAB, ', , '; => RETURN [sepr];
ENDCASE => RETURN [other];
};
ReadListOfRope:
PUBLIC
PROC [f:
IO.
STREAM]
RETURNS [ropeList:
LIST
OF Rope.
ROPE] = {
rope: Rope.ROPE;
end: BOOL ← FALSE;
ropeList ← NIL;
WHILE
TRUE
DO
[rope,
----] ←
IO.GetTokenRope[f, RopesOnOneLineProc
!IO.EndOfStream => {end ← TRUE; CONTINUE}];
IF end OR rope = NIL THEN RETURN;
IF Rope.Equal[rope, Rope.FromChar[IO.CR]] THEN RETURN
ELSE ropeList ← AppendRopeToRopeList[rope, ropeList];
ENDLOOP;
};
AppendRopeToRopeList:
PROC [rope: Rope.
ROPE, list:
LIST
OF Rope.
ROPE]
RETURNS [
LIST
OF Rope.
ROPE] = {
A copy of List.Nconc1 for LIST OF Rope.ROPE instead of LIST OF REF ANY
z: LIST OF Rope.ROPE ← list;
IF z = NIL THEN RETURN[CONS[rope,NIL]];
UNTIL z.rest = NIL DO z ← z.rest; ENDLOOP;
z.rest ← CONS[rope,NIL];
RETURN[list];
};
ReadVisibleAssemblies:
PUBLIC
PROC [f:
IO.
STREAM, scene: Scene, feedback: FeedbackData]
RETURNS [assemblyList:
LIST
OF Slice] = {
end: BOOL ← FALSE;
assembly: Slice;
assemblyName: Rope.ROPE;
continue, found: BOOL;
assemblyList ← NIL;
found ← TRUE;
WHILE continue
DO
[assemblyName,
----] ←
IO.GetTokenRope[f, RopesOnOneLineProc
!IO.EndOfStream => {end ← TRUE; CONTINUE}];
IF end OR assemblyName = NIL OR Rope.Equal[assemblyName, Rope.FromChar[IO.CR]] THEN continue ← FALSE
ELSE {
[assembly,
----] ← SVScene.FindAssemblyFromName[assemblyName, scene
! SVScene.AssemblyNotFound => {found ← FALSE; CONTINUE}];
IF
NOT found
THEN {
index: NAT ← IO.GetIndex[f];
Feedback.PutF[feedback, oneLiner, "Slice %g not found at: %g.", [rope[assemblyName]], [integer[index]]];
Feedback.Blink[feedback];
}
ELSE assemblyList ← AppendAssemblyToList[assembly, assemblyList];
};
ENDLOOP;
};
AppendAssemblyToList:
PROC [assembly: Slice, list:
LIST
OF Slice]
RETURNS [
LIST
OF Slice] = {
A copy of List.Nconc1 for LIST OF Slice instead of LIST OF REF ANY
z: LIST OF Slice ← list;
IF z = NIL THEN RETURN[CONS[assembly,NIL]];
UNTIL z.rest = NIL DO z ← z.rest; ENDLOOP;
z.rest ← CONS[assembly,NIL];
RETURN[list];
};
END.