DIRECTORY
Ascii USING [BS, CR, FF, SP, TAB],
BasicTime USING [earliestGMT, GMT, Now, Period, Unpack, Update],
Convert USING [RopeFromInt],
FileStream USING [OpenFileFromStream],
FS USING[ Delete, Error, GetInfo, nullOpenFile, Open, OpenFile, SetByteCountAndCreatedTime, StreamOpen ],
IO USING [Close, CreateStreamProcs, CreateStream, Flush, PutChar, PutF, PutFR, PutRope, STREAM, Value],
Loader USING [BCDBuildTime],
LupineMakeRpcModules
USING [
MakeRpcControlModule, MakeRpcClientModule,
MakeRpcClientBinderModule, MakeRpcServerModule ],
LupineManager USING [],
LupineManagerPrivate
USING [
Abort, Error,
ErrorCode, ErrorHandlerProc, ErrorType,
ExplanationProc, IsNull,
Language,
ModuleTypes, Nest, Options, ParamPassingMethod,
SHORT, String, StringNIL],
LupineMarshal USING [ParameterProtocolVersions],
LupineSymbolTable
USING [
CloseInterface, GetInterfaceInfo, GMT, InterfaceInfo,
OpenError, OpenInterface, VersionStampString, VersionStamp ],
Rope USING [Cat, Find, Length, ROPE, Substr];
codeFilename: String ← NIL;
codeStream: ARRAY [1..9] OF IO.STREAM ← ALL[NIL];
codeStreamIndex: ARRAY [1..9] OF LONG INTEGER ← ALL[0];
OutputFileCount: INT ← 1;
CurrentOutputFile: INT ← 1;
OpenCodeFile:
PUBLIC
PROCEDURE [codeModuleName: String, numberOfOutputFiles:
INT ← 1] =
BEGIN
OutputFileCount ← numberOfOutputFiles;
IF OutputFileCount = 1
THEN {
codeStream[1] ←
FS.StreamOpen[
fileName: ModuleDotMesa[codeModuleName],
accessOptions: $create ];
codeStreamIndex[1] ← 0;
}
ELSE {
nameBeforeImpl: String = codeModuleName.Substr[0, codeModuleName.Length[]-4];
FOR no:
INT
IN [1..OutputFileCount]
DO
name: String = nameBeforeImpl.Cat[Convert.RopeFromInt[from: no, showRadix: FALSE] , "Impl.mesa"];
codeStream[no] ←
FS.StreamOpen[
fileName: name,
accessOptions: $create ];
codeStreamIndex[no] ← 0;
ENDLOOP;
};
InitializeCodeLinePut;
CurrentOutputFile ← 0 ;
END;
OutputToAllFiles:
PUBLIC PROCEDURE = {
CurrentOutputFile ← 0 ;
} ;
NextOutputFile:
PUBLIC PROCEDURE = {
CurrentOutputFile ← CurrentOutputFile + 1;
IF CurrentOutputFile > OutputFileCount THEN CurrentOutputFile ← 1;
};
CodeStreamPut:
PROCEDURE [char:
CHARACTER] =
INLINE BEGIN
IF CurrentOutputFile = 0
THEN {
FOR no:
INT
IN [1..OutputFileCount]
DO
codeStream[no].PutChar[char];
codeStreamIndex[no] ← codeStreamIndex[no] + 1;
ENDLOOP;
}
ELSE {
codeStream[CurrentOutputFile].PutChar[char];
codeStreamIndex[CurrentOutputFile] ← codeStreamIndex[CurrentOutputFile] + 1;
};
END;
CodeStreamPutRope:
PROCEDURE [rope: String] =
INLINE BEGIN
IF CurrentOutputFile = 0
THEN {
FOR no:
INT
IN [1..OutputFileCount]
DO
codeStream[no].PutRope[rope];
codeStreamIndex[no] ← codeStreamIndex[no] + rope.Length[];
ENDLOOP;
}
ELSE {
codeStream[CurrentOutputFile].PutRope[rope];
codeStreamIndex[CurrentOutputFile] ← codeStreamIndex[CurrentOutputFile] + rope.Length[];
};
END;
GetCodeFileName:
PROC
RETURNS [String] =
INLINE {
RETURN[
IF IsNull[codeFilename]
THEN StringNIL
ELSE codeFilename ]};
GetCodeStreamIndex:
PROC
RETURNS [
LONG
INTEGER] =
INLINE {IF CurrentOutputFile = 0 THEN RETURN [codeStreamIndex[1]] ELSE RETURN[codeStreamIndex[CurrentOutputFile]]};
StampCodeFile:
PUBLIC
PROCEDURE [codeModuleName:String] =
BEGIN
moduleName, fileName: String;
now: ST.GMT = BasicTime.Now[];
year: INT = BasicTime.Unpack[now].year;
lupineTime: ST.GMT ← Loader.BCDBuildTime[];
moduleVersion: ST.VersionStamp;
moduleTime, sourceTime: ST.GMT;
[moduleName: moduleName, fileName: fileName, moduleVersion: moduleVersion,
moduleCreateTime: moduleTime, sourceCreateTime: sourceTime]
← ST.GetInterfaceInfo[];
CodeStreamPutRope[IO.PutFR["-- Copyright (C) %g by Xerox Corporation. All rights reserved.\n", [integer[year]]]];
CodeStreamPutRope[IO.PutFR[
"-- Stub file %g was translated on %g by Lupine of %g",
[rope[codeFilename]],
[time[now]],
[time[lupineTime]] ]];
CodeStreamPutRope[IO.PutFR["\n-- Source interface %g came from file %g, which was created on %g with version stamp %g from source of %g.\n",
[rope[moduleName]],
[rope[fileName]],
[time[moduleTime]],
[rope[ST.VersionStampString[stamp: moduleVersion]]],
[time[sourceTime]] ]];
END;
StampTranslationOptions:
PUBLIC
PROCEDURE [options: Options] =
BEGIN
LanguageString: ARRAY Language OF String = [Cedar: "Cedar", Mesa: "Mesa"];
ParamPassingString:
ARRAY ParamPassingMethod
OF String = [
Var: "VAR", Value: "VALUE", Result: "RESULT",
Handle: "HANDLE", InterMds: "InterMds" ];
BoolString: ARRAY BOOLEAN OF String = [TRUE: "TRUE", FALSE: "FALSE"];
oldest, newest: LONG INTEGER;
[oldestSupported: oldest, newestSupported: newest] ← Marshal.ParameterProtocolVersions[];
CodeStreamPutRope[IO.PutFR["
-- The parameters for this translation are:
-- Target language = %g
-- Default parameter passing = %g
-- Deallocate server heap arguments = %g
-- Inline RpcServerImpl dispatcher stubs = %g
-- Declare signals = %g",
[rope[LanguageString[options.targetLanguage]]],
[rope[ParamPassingString[options.defaultParamPassing]]],
[rope[BoolString[options.freeServerArguments]]],
[rope[BoolString[options.inlineServerDispatcherStubs]]],
[rope[BoolString[options.declareSignals]]]
]];
CodeStreamPutRope[IO.PutFR["
-- Warn about short POINTER (\"MDS\") allocations = %g
-- Maximum number of dynamic heap NEWs = %g, MDS NEWs = %g
-- Acceptable parameter protocols = VersionRange[%g..%g].\n",
[rope[BoolString[options.warnMDSAllocs]]],
[integer[options.maxHeapAllocations]],
[integer[options.maxMdsAllocations]],
[integer[oldest]],
[integer[newest]]
]];
END; -- StampTranslationOptions.
CloseCodeFile:
PUBLIC
PROCEDURE =
It is VERY important to call CloseCodeFile on any relevant UNWINDs.
BEGIN
FinalizeCodeLinePut[];
FOR no:
INT
IN [1..OutputFileCount]
DO
file: FS.OpenFile;
bytes: INT;
created: BasicTime.GMT ← BasicTime.earliestGMT;
codeStream[no].Flush[];
Insure that the generated mesa files do not have the same date. This is to help the version map work better.
file ← FileStream.OpenFileFromStream[codeStream[no]];
[bytes: bytes, created: created] ← file.GetInfo[];
IF BasicTime.Period[from: LastCodeFileGMT, to: created] <= 0
THEN {
created ← BasicTime.Update[base: LastCodeFileGMT, period: 1];
file.SetByteCountAndCreatedTime[bytes: bytes, created: created];
};
LastCodeFileGMT ← created;
codeStream[no].Close[];
codeStreamIndex[no] ← 0;
ENDLOOP;
codeFilename ← NIL;
END;
DeleteExistingCodeFiles:
PROCEDURE =
BEGIN
DeleteOne:
PROC [module: String] =
BEGIN
FS.Delete [
name: ModuleDotMesa[module]
! FS.Error => CONTINUE ];
END;
DeleteOne[ModuleName[control]];
DeleteOne[ModuleName[client]];
DeleteOne[ModuleName[server]];
END;
ModuleDotMesa:
PROCEDURE [moduleName: String]
RETURNS [String] =
INLINE BEGIN
RETURN[moduleName.Cat[".mesa"]]
END;
SpacesPerNest: INTEGER = 2;
SpacesPerTab: INTEGER = 4;
ExtraSpacesOnWrap: INTEGER = 2*SpacesPerNest;
ApproxMaxIdentifierLength: INTEGER = 12;
stillLeadingSpaces, doingComment: BOOLEAN;
lineLength, spaces, lastHyphen, lineWrapThreshhold: INTEGER;
formattedStream:
PUBLIC
IO.
STREAM ←
IO.CreateStream[
streamProcs: IO.CreateStreamProcs[variety: output, class: $Lupine, putChar: CodeLinePut],
streamData: NIL];
SetCodeLineLength:
PROCEDURE [desiredLineLength:
LONG
INTEGER] =
INLINE BEGIN
lineWrapThreshhold ←
MAX[
28,
SHORT[desiredLineLength]-ApproxMaxIdentifierLength-ExtraSpacesOnWrap ];
END;
InitializeCodeLinePut,
StartNewCodeLine:
PROCEDURE =
INLINE BEGIN
stillLeadingSpaces ← TRUE;
lineLength ← spaces ← 0;
lastHyphen ← -1;
doingComment ← FALSE;
END;
FinalizeCodeLinePut: PROCEDURE = INLINE {};
CodeLinePut: SAFE PROCEDURE[self: IO.STREAM, char: CHAR] = TRUSTED
This routine WILL wrap comments and string constants. Lupine
generates no troublesome strings (i.e., strings that are too long
or contain one or more hyphens). Comments should be wrapped OK.
The BS character is specially interpreted to mean start a new line
and indent for a continuation (as in a multiline record declaration).
BEGIN
WrapLine: PROC =
If the current line is indented all the way to the RIGHT margin
(lineWrapThreshhold), any further attempts to indent are ignored.
BEGIN
IF stillLeadingSpaces
THEN lineLength ← spaces ← lineWrapThreshhold
ELSE
BEGIN
lineLength ← spaces;
IF spaces >= lineWrapThreshhold THEN stillLeadingSpaces ← TRUE;
CodeStreamPut[Ascii.CR];
CodeStreamPutRope[IndentInline[(spaces+ExtraSpacesOnWrap)/SpacesPerNest]];
IF doingComment
THEN {
CodeStreamPutRope["-- "];
lineLength ← lineLength + 3; lastHyphen ← -1 };
END;
END; -- WrapLine.
ExtendToNextTabStop:
PROC [length:
INTEGER]
RETURNS [--lengthAtStop:-- INTEGER] =
INLINE {RETURN[SpacesPerTab*(length/SpacesPerTab+1)]};
SELECT char
FROM
Ascii.
SP =>
IF lineLength < lineWrapThreshhold
THEN {
lineLength ← lineLength + 1;
IF stillLeadingSpaces THEN spaces ← spaces + 1;
CodeStreamPut[Ascii.SP] }
ELSE WrapLine;
Ascii.
TAB =>
IF lineLength < lineWrapThreshhold
THEN {
lineLength ← ExtendToNextTabStop[lineLength];
IF stillLeadingSpaces THEN spaces ← ExtendToNextTabStop[spaces];
CodeStreamPut[Ascii.TAB] }
ELSE WrapLine;
Ascii.
CR, Ascii.
FF => {
StartNewCodeLine[];
CodeStreamPut[char] };
Ascii.BS => WrapLine; -- Special; BS not printed.
ENDCASE => {
stillLeadingSpaces ← FALSE;
lineLength ← lineLength + 1;
IF char = '-
THEN {
IF lastHyphen = lineLength-1
THEN doingComment ← ~doingComment ELSE lastHyphen ← lineLength };
CodeStreamPut[char] };
END; -- CodeLinePut.
WF1:
PUBLIC
PROC[format: Rope.
ROPE, v1:
IO.Value] =
BEGIN
formattedStream.PutF[format, v1];
END;
WFS,
WriteFormattedStrings:
PUBLIC
PROCEDURE [
s01, s02, s03: String←StringNIL ] =
BEGIN
IF s01 # StringNIL THEN formattedStream.PutRope[s01];
IF s02 # StringNIL THEN formattedStream.PutRope[s02];
IF s03 # StringNIL THEN formattedStream.PutRope[s03];
END;
WFSL,
WriteFormattedStringsLong:
PUBLIC
PROCEDURE [
s01, s02, s03, s04, s05, s06, s07, s08, s09, s10,
s11, s12, s13, s14, s15, s16, s17, s18: String←StringNIL] =
BEGIN
IF s01 # StringNIL THEN formattedStream.PutRope[s01];
IF s02 # StringNIL THEN formattedStream.PutRope[s02];
IF s03 # StringNIL THEN formattedStream.PutRope[s03];
IF s04 # StringNIL THEN formattedStream.PutRope[s04];
IF s05 # StringNIL THEN formattedStream.PutRope[s05];
IF s06 # StringNIL THEN formattedStream.PutRope[s06];
IF s07 # StringNIL THEN formattedStream.PutRope[s07];
IF s08 # StringNIL THEN formattedStream.PutRope[s08];
IF s09 # StringNIL THEN formattedStream.PutRope[s09];
IF s10 # StringNIL THEN formattedStream.PutRope[s10];
IF s11 # StringNIL THEN formattedStream.PutRope[s11];
IF s12 # StringNIL THEN formattedStream.PutRope[s12];
IF s13 # StringNIL THEN formattedStream.PutRope[s13];
IF s14 # StringNIL THEN formattedStream.PutRope[s14];
IF s15 # StringNIL THEN formattedStream.PutRope[s15];
IF s16 # StringNIL THEN formattedStream.PutRope[s16];
IF s17 # StringNIL THEN formattedStream.PutRope[s17];
IF s18 # StringNIL THEN formattedStream.PutRope[s18];
END;
WFL,
WriteFormattedLine:
PUBLIC
PROCEDURE [
nest: Nest, s01, s02, s03: String←StringNIL ] =
BEGIN
formattedStream.PutRope[IndentInline[nest]];
WFS[s01, s02, s03];
formattedStream.PutChar[Ascii.CR];
END;
WFL1,
WriteFormattedLine1:
PUBLIC
PROCEDURE [nest: Nest, s01: String] =
BEGIN
formattedStream.PutRope[IndentInline[nest]];
formattedStream.PutRope[s01];
formattedStream.PutChar[Ascii.CR];
END;
WFLL,
WriteFormattedLineLong:
PUBLIC
PROCEDURE [
nest: Nest, s01, s02, s03, s04, s05, s06: String←StringNIL ] =
BEGIN
formattedStream.PutRope[IndentInline[nest]];
WFSL[s01, s02, s03, s04, s05, s06];
formattedStream.PutChar[Ascii.CR];
END;
Indent:
PUBLIC
PROCEDURE [nest: Nest]
RETURNS [
--tabsAndSpaces:-- String] =
BEGIN
RETURN[ IndentInline[nest] ];
END;
IndentInline:
PROCEDURE [nest: Nest]
RETURNS [
--tabsAndSpaces:-- String] =
INLINE BEGIN
RETURN[ NestTable[MIN[nest,LAST[NestTableIndex]]] ];
END;
NestTableIndex: TYPE = Nest[0..30];
NestTable: PACKED ARRAY NestTableIndex OF String = [
These constants must have SpacesPerNest spaces per nest.
--00-- "",
--01-- " ",
--02-- " ",
--03-- " ",
--04-- " ",
--05-- " ",
--06-- " ",
--07-- " ",
--08-- " ",
--09-- " ",
--10-- " ",
--11-- " ",
--12-- " ",
--13-- " ",
--14-- " ",
--15-- " ",
--16-- " ",
--17-- " ",
--18-- " ",
--19-- " ",
--20-- " ",
--21-- " ",
--22-- " ",
--23-- " ",
--24-- " ",
--25-- " ",
--26-- " ",
--27-- " ",
--28-- " ",
--29-- " ",
--30-- " " ];
No module initialization.
END. -- LupineManagerImpl.