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 ];
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;
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: BOOL ← FALSE;
freeServerArgs: BOOL ← TRUE;
inlineDispatcherStubs: BOOL ← TRUE;
declareSignals: BOOL ← TRUE;
warnMDSAllocs: BOOL ← TRUE;
maxHeapAllocs: INT ← 50;
maxMdsAllocs: INT ← 50;
lineLength: INT ← 82;
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.ROPE ← NIL;
DO key: Rope.
ROPE;
args: LIST OF Rope.ROPE ← NIL;
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: BOOLEAN ← FALSE;
HandleError: LupineManager.ErrorHandlerProc =
PROCEDURE [type: ErrorType, code: ErrorCode,
codeExplanation: String,
outputFileName: String←StringNIL,
outputFileCharPosition: LONG INTEGER,
problemCausingText: String←NIL ]
RETURNS [abortTranslation: BOOLEANLSE];
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;