File LupineUserInterfaceImpl.mesa.
Last edited by BZM on 2-May-82 23:18:33.
Last Edited by: Birrell, September 14, 1983 8:22 am
DIRECTORY
Ascii USING [CR, LF, SP, TAB ],
Commander USING [CommandProc, Register],
IO,
Loader USING [BCDBuildTime],
LupineManager USING [ErrorHandlerProc, Language, ParamPassingMethod, String, TranslateRemoteInterface],
Rope USING[ Equal, Fetch, Length, ROPE ];
LupineUserInterfaceImpl: CEDAR MONITOR
IMPORTS Commander, IO, Loader, LupineManager, Rope =
BEGIN
inUse: BOOLFALSE;
finished: CONDITION;
Wait: ENTRY PROC[out: IO.STREAM] =
BEGIN
ENABLE UNWIND => NULL;
wait: BOOL = inUse;
IF wait THEN out.PutRope["Waiting for other use of Lupine to finish ... "];
WHILE inUse DO WAIT finished ENDLOOP;
inUse ← TRUE;
IF wait THEN out.PutRope["ok\n"];
END;
Finish: ENTRY PROC =
{ inUse ← FALSE; NOTIFY finished };
DoIt: Commander.CommandProc--cmd: Commander.Handle-- =
BEGIN
in: IO.STREAM = cmd.in;
out: IO.STREAM = cmd.out;
targetLanguage: LupineManager.Language ← Cedar;
defaultParamPassing: LupineManager.ParamPassingMethod ← Value;
interMdsCalls: BOOLFALSE;
freeServerArgs: BOOLTRUE;
inlineDispatcherStubs: BOOLTRUE;
declareSignals: BOOLTRUE;
warnMDSAllocs: BOOLTRUE;
maxHeapAllocs: INT ← 50;
maxMdsAllocs: INT ← 50;
lineLength: INT ← 82;
CheckAbort: PROC =
{};
MyBreak: IO.BreakProc =
BEGIN
SELECT char FROM
Ascii.SP, Ascii.CR, Ascii.TAB, Ascii.LF, ', => RETURN[sepr];
'[, '], ', => RETURN[break];
ENDCASE => RETURN[other];
END;
SyntaxError: ERROR = CODE;
ParseLine: PROC[commandStr: IO.STREAM] =
BEGIN
GetToken: PROC RETURNS[Rope.ROPE] =
{ RETURN[ commandStr.GetTokenRope[MyBreak].token ] };
nextToken: Rope.ROPENIL;
DO key: Rope.ROPE;
args: LIST OF Rope.ROPENIL;
argCount: INT ← 0;
IF nextToken = NIL THEN nextToken ← GetToken[ ! IO.EndOfStream => EXIT];
key ← nextToken; nextToken ← NIL;
IF key.Equal[","] THEN LOOP;
IF key.Length[] = 0 THEN EXIT -- end of stream! --;
nextToken ← GetToken[ ! IO.EndOfStream => { nextToken ← NIL; CONTINUE } ];
IF nextToken.Equal["["]
THEN BEGIN
DO nextToken ← GetToken[ ! IO.EndOfStream => GOTO missingClose];
IF nextToken.Equal["]"] THEN EXIT;
IF nextToken.Equal[","] THEN LOOP;
IF args = NIL
THEN args ← CONS[first: nextToken, rest: NIL]
ELSE args.rest ← CONS[first: nextToken, rest: NIL];
argCount ← argCount+1;
ENDLOOP;
nextToken ← NIL;
EXITS missingClose =>
{ out.PutF["Missing \"]\"\n"]; ERROR SyntaxError[] };
END;
DoCommand[key, args, argCount];
ENDLOOP;
END;
DoCommand: PROC[key: Rope.ROPE, args: LIST OF Rope.ROPE, argCount: INT] =
BEGIN
SELECT TRUE FROM
key.Equal["Help", FALSE] =>
{ Help[] };
key.Equal["TranslateInterface", FALSE] =>
{ IF argCount # 1 THEN GOTO wrong; TranslateInterface[args.first] };
key.Equal["TargetLanguage", FALSE] =>
{ IF argCount # 1 THEN GOTO wrong; SetTargetLanguage[args.first] };
key.Equal["DefaultParameterPassing", FALSE] =>
{ IF argCount # 1 THEN GOTO wrong; SetParameterPassing[args.first] };
key.Equal["InterMdsCalls", FALSE] =>
{ IF argCount # 1 THEN GOTO wrong; SetInterMdsCalls[args.first] };
key.Equal["FreeServerArguments", FALSE] =>
{ IF argCount # 1 THEN GOTO wrong; SetFreeServerArgs[args.first] };
key.Equal["InlineDispatcherStubs", FALSE] =>
{ IF argCount # 1 THEN GOTO wrong; SetInlineStubs[args.first] };
key.Equal["DynamicHeapNEWs", FALSE] =>
{ IF argCount # 2 THEN GOTO wrong; SetDynamicHeapNEWs[args.first, args.rest.first] };
key.Equal["LineLength", FALSE] =>
{ IF argCount # 1 THEN GOTO wrong; SetLineLength[args.first] };
key.Equal["DeclareSignals", FALSE] =>
{ IF argCount # 1 THEN GOTO wrong; SetDeclareSignals[args.first] };
key.Equal["WarnMDSAllocs", FALSE] =>
{ IF argCount # 1 THEN GOTO wrong; SetWarnMDSAllocs[args.first] };
argCount = 0 => TranslateInterface[key];
ENDCASE =>
{ out.PutF["Unknown command \"%g\"\n", [rope[key]]]; ERROR SyntaxError[] };
EXITS wrong =>
{ out.PutF["Wrong number of arguments to the \"%g\" command\n", [rope[key]]];
ERROR SyntaxError[] };
END;
Help: PROC =
BEGIN
out.PutRope["Lupine accepts command lines of the form:

Lupine command[args] command[args] command[args] . . .

The following commands are available (\"TranslateInterface[module]\" may be shortened to \"module\").

Help[]
-- prints this message
TranslateInterface[interfaceName]
-- produces the RPC stubs modules for that interface
TargetLanguage[{Cedar,Mesa} ← Cedar]
-- allows production of Pilot-compatible stubs (which can't be run under Cedar)
DefaultParameterPassing[{Var, Value, Result, Handle} ← Value]
-- default parameter passing mode
InterMdsCalls[BOOL ← FALSE]
-- produces stubs for non-remote calls (archaic?)
FreeServerArguments[BOOL ← TRUE]
-- \"FALSE\" prevents de-allocation of POINTER referents after server procedure calls
InlineDispatcherStubs[BOOL ← TRUE]
-- \"FALSE\" is needed for large interfaces to prevent compiler storage overflow
DynamicHeapNEWs[long: INT ← 50, short: INT ← 50]
-- limit on dynamic storage allocations for (LONG) POINTER referents.
LineLength[INT ← 82]
-- length of lines produced in stub sources
DeclareSignals[BOOL ← TRUE]
-- \"FALSE\" means someone else will declare (and export) the interface's signals
WarnMDSAllocs[BOOL ← TRUE]
-- \"FALSE\" means suppress warnings about short POINTER (\"MDS\") allocations
"];
END;
TranslateInterface: PROCEDURE [interfaceFile: Rope.ROPE] =
BEGIN
aborted, errors, warnings: BOOLEANFALSE;
HandleError: LupineManager.ErrorHandlerProc =
PROCEDURE [type: ErrorType, code: ErrorCode,
codeExplanation: String,
outputFileName: String←StringNIL,
outputFileCharPosition: LONG INTEGER,
problemCausingText: String←NIL ]
RETURNS [abortTranslation: BOOLEAN�LSE];
BEGIN
CheckAbort[];
out.PutChar['\n];
SELECT type FROM
abort => { aborted ← TRUE; out.PutRope["\nFatal error"] };
error => { errors ← TRUE; out.PutRope["\nError"] };
warning => { warnings ← TRUE; out.PutRope["\nWarning"] };
ENDCASE => NULL;
IF outputFileName.Length[] # 0
THEN out.PutF[" at %g[%g]", [rope[outputFileName]], [integer[outputFileCharPosition]]];
out.PutF[":\n %g", [rope[codeExplanation]]];
IF problemCausingText.Length[] # 0
THEN out.PutF["\n Problem-causing file, module, identifier, or type: %g",
[rope[problemCausingText]] ];
RETURN [abortTranslation: FALSE];
END; -- HandleError.
CheckAbort[];
out.PutF["Translating %g ... ", [rope[interfaceFile]] ];
TRUSTED{ LupineManager.TranslateRemoteInterface[
interfaceBcdFilename: interfaceFile,
errorHandler: HandleError,
options: [
targetLanguage: targetLanguage,
defaultParamPassing: (IF interMdsCalls THEN InterMds ELSE defaultParamPassing),
freeServerArguments: freeServerArgs,
inlineServerDispatcherStubs: inlineDispatcherStubs,
declareSignals: declareSignals,
warnMDSAllocs: warnMDSAllocs,
maxHeapAllocations: maxHeapAllocs,
maxMdsAllocations: maxMdsAllocs ],
desiredLineLength: lineLength ] };
IF aborted OR errors OR warnings THEN out.PutChar['\n];
out.PutF["\nTranslation of %g %g.\n",
[rope[interfaceFile]],
[rope[SELECT TRUE FROM
aborted => "aborted",
errors => "finished with errors",
warnings => "finished with warnings",
ENDCASE => "complete"]] ];
END; -- TranslateInterface.
Bool: PROC[arg: Rope.ROPE] RETURNS[BOOL] =
BEGIN
SELECT TRUE FROM
Rope.Equal[arg, "TRUE", FALSE] => RETURN[TRUE];
Rope.Equal[arg, "FALSE", FALSE] => RETURN[FALSE];
ENDCASE => { out.PutRope["\"TRUE\" or \"FALSE\" expected\n"]; ERROR SyntaxError[] };
END;
Int: PROC[arg: Rope.ROPE] RETURNS[val: INT ← 0] =
BEGIN
FOR i: CARDINAL IN CARDINAL[0..arg.Length[])
DO c: CHAR = arg.Fetch[i];
IF c IN ['0..'9]
THEN val ← val * 10 + (c-'0)
ELSE { out.PutRope["Decimal number expected\n"]; ERROR SyntaxError[] };
ENDLOOP;
END;
SetTargetLanguage: PROCEDURE [language: Rope.ROPE] =
BEGIN
SELECT TRUE FROM
Rope.Equal[language, "Cedar", FALSE] => targetLanguage ← Cedar;
Rope.Equal[language, "Mesa", FALSE] => targetLanguage ← Mesa;
ENDCASE => { out.PutRope["Unknown target language\n"]; ERROR SyntaxError[] };
END;
SetParameterPassing: PROCEDURE [kind: Rope.ROPE] =
BEGIN
SELECT TRUE FROM
Rope.Equal[kind, "VAR", FALSE] => defaultParamPassing ← Var;
Rope.Equal[kind, "VALUE", FALSE] => defaultParamPassing ← Value;
Rope.Equal[kind, "RESULT", FALSE] => defaultParamPassing ← Result;
Rope.Equal[kind, "HANDLE", FALSE] => defaultParamPassing ← Handle;
ENDCASE => { out.PutRope["Unknown parameter mode\n"]; ERROR SyntaxError[] };
END;
SetInterMdsCalls: PROCEDURE [onOff: Rope.ROPE] =
{ interMdsCalls ← Bool[onOff] };
SetFreeServerArgs: PROCEDURE [onOff: Rope.ROPE] =
{ freeServerArgs ← Bool[onOff] };
SetInlineStubs: PROCEDURE [onOff: Rope.ROPE] =
{ inlineDispatcherStubs ← Bool[onOff] };
SetDynamicHeapNEWs: PROCEDURE [heap, mds: Rope.ROPE] =
{ maxHeapAllocs ← Int[heap]; maxMdsAllocs ← Int[mds] };
SetLineLength: PROCEDURE [length: Rope.ROPE] =
{ lineLength ← Int[length] };
SetDeclareSignals: PROCEDURE [onOff: Rope.ROPE] =
{ declareSignals ← Bool[onOff] };
SetWarnMDSAllocs: PROCEDURE [onOff: Rope.ROPE] =
{ warnMDSAllocs ← Bool[onOff] };
TRUSTED{ out.PutF["Lupine version 1.1 of %g.\n\n",
[time[Loader.BCDBuildTime[]]] ] };
Wait[out];
ParseLine[IO.RIS[cmd.commandLine] !
SyntaxError => CONTINUE;
UNWIND => Finish[] ];
Finish[];
END;
Module Initialization.
Commander.Register[key: "Lupine",
proc: DoIt,
doc: "Produces stub modules for Cedar RPC; type \"Lupine Help\" for details"];
END.