file: TexSysdepImpl.mesa
Edit by Michael Plass, December 27, 1982 12:37 pm
Edit by Ramshaw, February 4, 1984 9:56 pm
Last Edited by: Pavel, October 12, 1985 4:09:08 pm PDT
DIRECTORY
BasicTime,
Commander,
FS,
IO,
MessageWindow,
PascalBasic,
PascalWizardFiles,
Process,
Rope,
SirPress,
TexTypes,
TexInit,
TexSysdep,
TexSysdepInline,
TexInteraction,
TexMemory,
TexSymbols,
TexScan,
TexDvi,
TexOps,
TexParagraph,
TexBuildPage,
TexMath,
TexRest,
TexExtensions,
TeXExport,
UserProfile USING [Token];
TexSysdepImpl: PROGRAM
IMPORTS PascalBasic, PascalWizardFiles, TexInteraction, TexScan, TexDvi, TexSysdepInline, TexRest, SirPress, FS, IO, Rope, UserProfile, BasicTime, Process, TexSymbols, TexOps, MessageWindow
EXPORTS TexSysdep, TeXExport
= BEGIN OPEN PascalBasic, PascalWizardFiles, TexTypes, TexInteraction;
RopeFromNameOfFile: PROCEDURE [] RETURNS [fileName: Rope.ROPE] = {
i: NAT ← 0;
P: SAFE PROC RETURNS [CHAR] = TRUSTED {i ← i+1; RETURN[TexInteraction.NameOfFile[i]]};
length: NAT ← 0;
WHILE length<TexTypes.FileNameSize AND TexInteraction.NameOfFile[length+1]#' DO
length ← length+1;
ENDLOOP;
fileName ← Rope.FromProc[length, P];
IF i#length THEN ERROR;
};
NameOfFileFromRope: PRIVATE PROCEDURE [r: Rope.ROPE] = {
NameLength ← MIN[r.Length[], FileNameSize];
FOR i: [1..FileNameSize] IN [1..NameLength] DO
NameOfFile[i]←r.Fetch[i-1] ENDLOOP;
FOR i: [1..FileNameSize] IN (NameLength..NAT[FileNameSize]] DO
NameOfFile[i] ← ' ; ENDLOOP;
};
DefaultInputsDirectory: PROCEDURE RETURNS [inputs: Rope.ROPE] = {
inputs ← UserProfile.Token[key: "TeX.DefaultInputsDirectory",
default: "/Cyan/TeX/Inputs/"];
};
ReadProfileForDirectories: PUBLIC PROCEDURE = {
inputs: Rope.ROPE ← DefaultInputsDirectory[];
fonts: Rope.ROPE←UserProfile.Token[key: "TeX.DefaultFontMetricsDirectory",
default: "///Fonts/FontMetrics/"];
NameOfFileFromRope[inputs];
TexArea ← TexScan.MakeNameString[];
NameOfFileFromRope[fonts];
TexFontArea ← TexScan.MakeNameString[];
};
SetPoolName: PUBLIC PROCEDURE = {
poolName: Rope.ROPE = Rope.Cat[DefaultInputsDirectory[], "TeX.pool"];
FOR i:NAT IN [0 .. NAT[poolName.Length]) DO
TexInteraction.NameOfFile[i+1] ← poolName.Fetch[i];
ENDLOOP;
FOR i:NAT IN [NAT[poolName.Length] .. 127) DO
TexInteraction.NameOfFile[i+1] ← ' ;
ENDLOOP;
};
ResetTermIn: PUBLIC PROCEDURE [F: LONG POINTER TO AlphaFile] = {
PascalOpenTextFileTTYInput[F];
};
RewriteTermOut: PUBLIC PROCEDURE [F: LONG POINTER TO AlphaFile] = {
PascalOpenTextFileTTYOutput[F];
};
ScreamAboutIllegalPrintFileFormat: PRIVATE PROC = {
MessageWindow.Append["Error in your Profile: TeX.PrintFileFormat must be Press or DVI!", TRUE];
MessageWindow.Blink[];
ERROR ABORTED;
};
ProfileAsksForPress: PUBLIC PROCEDURE RETURNS [BOOLEAN] = {
fmt: Rope.ROPE ← UserProfile.Token[key: "TeX.PrintFileFormat", default: "Press"];
SELECT TRUE FROM
Rope.Equal[s1: fmt, s2: "Press", case: FALSE] => RETURN[TRUE];
Rope.Equal[s1: fmt, s2: "DVI", case: FALSE] => RETURN[FALSE];
ENDCASE => ScreamAboutIllegalPrintFileFormat;
RETURN[TRUE];
};
PressOpenOut: PUBLIC PROCEDURE RETURNS [BOOLEAN] = {
TexSysdepInline.pressFileStream ← FS.StreamOpen[RopeFromNameOfFile[], $create !
FS.Error => TRUSTED{GOTO openFailed}];
TexSysdepInline.pressHandle ← SirPress.Create[TexSysdepInline.pressFileStream,
RopeFromNameOfFile[], NIL, normal, NIL];
TexSysdepInline.pyping ← FALSE;
TexSysdepInline.pype ← SirPress.NewPipe[TexSysdepInline.pypePosnsLimit];
RETURN[TRUE];
EXITS
openFailed => RETURN[FALSE];
};
ReadTheClock: PUBLIC PROCEDURE [Ttime, Dday, Mmonth, Yyear: LONG POINTER TO INT] = {
now: BasicTime.Unpacked�sicTime.Unpack[BasicTime.Now[]];
Ttime^ ← now.hour*BasicTime.minutesPerHour+now.minute;
Dday^ ← now.day;
Mmonth^ ← SELECT now.month FROM
January=>1, February=>2, March=>3,
April=>4, May=>5, June=>6,
July=>7, August=>8, September=>9,
October=>10, November=>11, December=>12,
ENDCASE=>ERROR;
Yyear^ ← now.year;
};
AOpenIn: PUBLIC PROCEDURE [F: LONG POINTER TO AlphaFile]
RETURNS [AOpenInResult: PascalBoolean] = {
inStream: IO.STREAM;
AOpenInResult ← TRUE;
inStream ← FS.StreamOpen[RopeFromNameOfFile[]
! FS.Error => TRUSTED {Post[error]; AOpenInResult ← FALSE; GO TO Quit}
];
PascalOpenTextFileWithStream[F, inStream];
PascalTextRESET[F];
EXITS Quit => NULL
};
AOpenOut: PUBLIC PROCEDURE [F: LONG POINTER TO AlphaFile]
RETURNS [AOpenOutResult: PascalBoolean] = {
outStream: IO.STREAM;
AOpenOutResult ← TRUE;
outStream ← FS.StreamOpen[RopeFromNameOfFile[], $create
! FS.Error => TRUSTED {Post[error]; AOpenOutResult ← FALSE; GO TO Quit}
];
PascalOpenTextFileWithStream[F, outStream];
PascalTextREWRITE[F];
EXITS Quit => NULL
};
BOpenIn: PUBLIC PROCEDURE [F: LONG POINTER TO ByteFile]
RETURNS [BOpenInResult: PascalBoolean] = {
inStream: IO.STREAM;
so: FS.StreamOptions ← FS.defaultStreamOptions;
so[tiogaRead] ← FALSE;
BOpenInResult ← TRUE;
inStream ← FS.StreamOpen[fileName: RopeFromNameOfFile[], streamOptions: so
! FS.Error => TRUSTED {Post[error]; BOpenInResult ← FALSE; GO TO Quit}
];
PascalOpenFileWithStream[@(F^.baseFile), inStream];
PascalRESET[file: @(F^.baseFile), length: 1, element: @(F^.element)];
EXITS Quit => NULL
};
BOpenOut: PUBLIC PROCEDURE [F: LONG POINTER TO ByteFile]
RETURNS [BOpenOutResult: PascalBoolean] = {
outStream: IO.STREAM;
BOpenOutResult ← TRUE;
outStream ← FS.StreamOpen[RopeFromNameOfFile[], $create
! FS.Error => TRUSTED {Post[error]; BOpenOutResult ← FALSE; GO TO Quit}
];
PascalOpenFileWithStream[@(F^.baseFile), outStream];
EXITS Quit => NULL
};
WOpenIn: PUBLIC PROCEDURE [F: LONG POINTER TO WordFile]
RETURNS [WOpenInResult: PascalBoolean] = {
inStream: IO.STREAM;
so: FS.StreamOptions ← FS.defaultStreamOptions;
so[tiogaRead] ← FALSE;
WOpenInResult ← TRUE;
inStream ← FS.StreamOpen[fileName: RopeFromNameOfFile[], streamOptions: so
! FS.Error => TRUSTED {Post[error]; WOpenInResult ← FALSE; GO TO Quit}
];
PascalOpenFileWithStream[@(F^.baseFile), inStream];
PascalRESET[file: @(F^.baseFile), length: 4, element: @(F^.element)];
EXITS Quit => NULL
};
WOpenOut: PUBLIC PROCEDURE [F: LONG POINTER TO WordFile]
RETURNS [WOpenOutResult: PascalBoolean] = {
outStream: IO.STREAM;
WOpenOutResult ← TRUE;
outStream ← FS.StreamOpen[RopeFromNameOfFile[], $create
! FS.Error => TRUSTED {Post[error]; WOpenOutResult ← FALSE; GO TO Quit}
];
PascalOpenFileWithStream[@(F^.baseFile), outStream];
EXITS Quit => NULL
};
Post: PRIVATE PROCEDURE [e: FS.ErrorDesc] = {
IF e.group # user THEN
{MessageWindow.Append[message: e.explanation, clearFirst: TRUE];
MessageWindow.Blink};
};
AClose: PUBLIC PROCEDURE [F: LONG POINTER TO AlphaFile] = {
PascalCloseTextFile[F];
};
BClose: PUBLIC PROCEDURE [F: LONG POINTER TO ByteFile] = {
PascalCloseFile[@(F^.baseFile)];
};
WClose: PUBLIC PROCEDURE [F: LONG POINTER TO WordFile] = {
PascalCloseFile[@(F^.baseFile)];
};
AMakeNameString: PUBLIC PROCEDURE [F: LONG POINTER TO AlphaFile]
RETURNS [AMakeNameStringResult: StrNumber] =
{RETURN[MakeNameStringFromFileStream[F^.baseFile^.str]]};
BMakeNameString: PUBLIC PROCEDURE [F: LONG POINTER TO ByteFile]
RETURNS [BMakeNameStringResult: StrNumber] =
{RETURN[MakeNameStringFromFileStream[F^.baseFile^.str]]};
WMakeNameString: PUBLIC PROCEDURE [F: LONG POINTER TO WordFile]
RETURNS [WMakeNameStringResult: StrNumber] =
{RETURN[MakeNameStringFromFileStream[F^.baseFile^.str]]};
PressMakeNameString: PUBLIC PROCEDURE
RETURNS [PressMakeNameStringResult: StrNumber] =
{RETURN[MakeNameStringFromFileStream[TexSysdepInline.pressFileStream]]};
MakeNameStringFromFileStream: PRIVATE PROCEDURE [s: IO.STREAM]
RETURNS [StrNumber] =
{local, global, name: Rope.ROPE;
[fullFName: local, attachedTo: global] ← FS.GetName[FS.OpenFileFromStream[s]];
IF global = NIL THEN name ← local ELSE name ← global;
NameOfFileFromRope[name];
RETURN[TexScan.MakeNameString[]]};
finalDviBufLength: NAT = 8;
finalDviBuf: REF TEXTNEW[TEXT[finalDviBufLength]];
WriteDvi: PUBLIC PROCEDURE [A, B: DviIndex] = {
outPtr: NAT ← 0;
IF TexSymbols.UsePressFormat THEN RETURN;
finalDviBuf.length ← finalDviBufLength;
FOR i: NAT IN [A..B] DO
finalDviBuf[outPtr] ← LOOPHOLE[TexDvi.DviBuf[i]];
outPtr ← outPtr+1;
IF outPtr=finalDviBufLength THEN {
TexScan.DviFile.baseFile.str.PutBlock[finalDviBuf];
outPtr ← 0;
};
ENDLOOP;
IF outPtr>0 THEN {
finalDviBuf.length ← outPtr;
TexScan.DviFile.baseFile.str.PutBlock[finalDviBuf];
};
};
FileGetPos: PUBLIC PROC [F: PascalTextFilePtr] RETURNS [FileGetPosResult: PascalInteger] =
BEGIN
FileGetPosResult ← 0; -- in case of error below
FileGetPosResult ← F.baseFile.str.GetIndex[ ! IO.Error =>
IF ec = NotImplementedForThisStream THEN CONTINUE];
END;
RopeFromStringNumber: PROCEDURE [s: StrNumber] RETURNS [r: Rope.ROPE] = {
i: PoolPointer ← StrStart^[s];
length: NAT ← StrStart^[s+1]-i;
P: SAFE PROC RETURNS [c:CHAR] = TRUSTED
{c ← Xchr[StrPool[i]]; i ← i+1};
r ← Rope.FromProc[length, P];
RETURN[r];
};
GetPypeCode: PUBLIC PROCEDURE [F: InternalFontNumber, AtSizeInHnm:PascalInteger]
RETURNS [GetPypeCodeResult: CedarNat] =
{
IF TexSysdepInline.pyping THEN FlushPype[];
RETURN[SirPress.GetFontCode[
p: TexSysdepInline.pressHandle,
family: RopeFromStringNumber[TexOps.FontFamily[F]],
size: AtSizeInHnm+50, --round instead of truncating, to avoid font substitutions
face: TexOps.FontFace[F],
rotation: 0,
unit: 100]];
};
PressSetFont: PUBLIC PROCEDURE [C: NAT] = {
IF TexSysdepInline.pyping THEN FlushPype[];
SirPress.SetFontFromCode[TexSysdepInline.pressHandle, C];
};
PressShowRule: PUBLIC PROCEDURE [Xstart, Ystart, Xlen, Ylen: INT] = {
IF TexSysdepInline.pyping THEN FlushPype[];
SirPress.PutRectangle[p: TexSysdepInline.pressHandle,
xstart: Xstart,
ystart: Ystart,
xlen: Xlen,
ylen: Ylen,
unit: 100]};
FlushPype: PUBLIC PROCEDURE = {
IF TexSysdepInline.pyping THEN
{ SirPress.ClosePipe[
p: TexSysdepInline.pressHandle,
pipe: TexSysdepInline.pype,
y: TexSysdepInline.yCoord];
TexSysdepInline.pyping ← FALSE};
};
PressWritePage: PUBLIC PROCEDURE = {
IF TexSysdepInline.pyping THEN FlushPype[];
SirPress.WritePage[TexSysdepInline.pressHandle];
};
PressCloseFile: PUBLIC PROCEDURE = {
SirPress.ClosePress[TexSysdepInline.pressHandle];
};
SetNormalPriority: PUBLIC PROCEDURE = {
Process.SetPriority[Process.priorityNormal];
};
SetBackgroundPriority: PUBLIC PROCEDURE = {
Process.SetPriority[Process.priorityBackground];
};
The following procedure reads the command line and returns one of three different values, encoded as integers: 0=> {command line was all blank}; 1=> {command line had non-blank stuff, and it has been loaded into the buffer}; -1=> {command line had so much non-blank stuff that it overflowed the buffer (which is unlikely, but we are running with bounds checks off, so it pays to be careful)}.
StuffOnCmdLine: PUBLIC PROCEDURE RETURNS [StuffOnCmdLineResult: INT] = {
tail: Rope.ROPE ← PascalBasic.commandLineTail;
cmdStr: IO.STREAMIO.RIS[tail];
curChar: CHAR;
myLoc: NAT ← First;
lastNonBlank: NAT;
DO
curChar ← '\n; -- in case of EndOfStream
curChar ← cmdStr.GetChar[! IO.EndOfStream => CONTINUE];
SELECT curChar FROM
' => LOOP; -- ignore leading whitespace
'\n => RETURN[0]; -- everything was blank
ENDCASE => EXIT; -- aha, a nonblank
ENDLOOP;
IF myLoc >= BufSize-1 THEN RETURN[-1];
Buffer[myLoc] ← Xord[curChar];
myLoc ← myLoc+1;
lastNonBlank ← myLoc;
DO
curChar ← '\n; -- in case of EndOfStream
curChar ← cmdStr.GetChar[! IO.EndOfStream => CONTINUE];
IF curChar = '\n THEN EXIT;
IF myLoc >= BufSize-1 THEN RETURN[-1];
Buffer[myLoc] ← Xord[curChar];
myLoc ← myLoc+1;
IF curChar # ' THEN lastNonBlank ← myLoc;
ENDLOOP;
Last ← lastNonBlank;
TexSymbols.CurInput.LocField ← First;
RETURN[1]};
RopeFromBuffer: PRIVATE PROCEDURE [A: INT, B: INT] RETURNS [Rope.ROPE]= {
i: NATA-1;
P: SAFE PROC RETURNS [CHAR] = TRUSTED {i ← i+1; RETURN[Xchr[Buffer[i]]]};
RETURN[Rope.FromProc[B-A+1, P]];
};
PackBufferedName: PUBLIC PROCEDURE [A: INT, B: INT] = {
NameOfFileFromRope[Rope.Cat[RopeFromBuffer[A,B], ".fmt"]];
};
DefaultFormatFile: PROCEDURE RETURNS [default: Rope.ROPE] = {
default ← UserProfile.Token[key: "TeX.DefaultFormatFile",
default: "/Cyan/TeX/Formats/Plain.fmt"];
};
PackDefaultArea: PUBLIC PROCEDURE [A: INT, B: INT] = {
default: Rope.ROPE ← DefaultFormatFile[];
cp: FS.ComponentPositions;
fullName: Rope.ROPE;
[fullName, cp] ← FS.ExpandName[default];
NameOfFileFromRope[Rope.Cat[
fullName.Substr[start:0, len: cp.base.start],
RopeFromBuffer[A,B],
".fmt"]];
};
PackAllDefault: PUBLIC PROCEDURE = {
default: Rope.ROPE ← DefaultFormatFile[];
NameOfFileFromRope[default];
};
The following describes how the registration of the various TeX commands works.
The file TeX.bcd contains only one registration, the automatically-produced one that PasMesa generates for ``Tex''. That one has a clientData of NIL, useless documentation and is an ``interpreted'' command.
There are two auxillary BCD files which can be run after TeX.bcd, one for registering the Local versions of the commands (LocalTeXCommands.bcd) and one for use on the Compute Server (RemoteTeXServerCommands.bcd).
There are two reasons why things are done in this arcane way:
1) In order to be sure of overriding the default PasMesa registration, we need to wait until after TeX.bcd has been run before doing our work.
2) In order to make it easy to maintain the differences between the conventions of the CommandTool and those of the Compute Server.
ExclusiveProc: PUBLIC Commander.CommandProc =
TRUSTED { [result, msg] ← PascalBasic.ExclusiveProc[cmd]; };
This simply makes PascalBasic.ExclusiveProc accessible to the auxillary BCDs.
TwiddlePascal: PUBLIC SAFE PROC = TRUSTED {
PascalBasic.SubsystemProcRec.p ← TexOrInitexDependingUponClientData;
};
TexOrInitexDependingUponClientData: PascalBasic.UnsafeCommandProc = {
actLikeInitex: REF BOOLNARROW[PascalBasic.clientData];
TexRest.StartLikeInitex ← actLikeInitex^;
TexRest.TheRealTex;
};
InterruptTex: PUBLIC Commander.CommandProc = CHECKED {
Interrupt ← 1;
};
END.