[cmd: Handle] RETURNS [result: REF ← NIL, msg: ROPE ← NIL]
CommandObject = [in, out, err: STREAM, commandLine, command: ROPE, ...]
ProcessArgument:
PROC [arg:
ROPE] = {
table: RedBlackTree.Table ← RedBlackTree.Create[getKey: GetKey, compare: Compare];
myData: MyData ← NEW[MyDataRep ← [table: table, errs: out]];
dfName: ROPE ← Rope.Concat[arg, ".df"];
outName: ROPE ← Rope.Concat[arg, ".depends"];
Process.CheckForAbort[];
[] ← GenerateDFClosure.GenerateClosureToProc[dfName, out, EachFile, myData, [toFork: forkers, followImports:
NOT switches['s]]
! ABORTED, UNWIND => myData.abortRequested ← TRUE];
Now that we have out data structure, we should print it.
First Char:
[charSet: 0, char: '\n, looks: LOOKS[], format: NIL, comment: FALSE, endOfNode: TRUE, deltaLevel: 1, propList: LIST[^[key: $FromTiogaFile, val: $Yes]]]
Comment Char:
[charSet: 0, char: 'F, looks: LOOKS[], format: $code, comment: TRUE, endOfNode: FALSE, deltaLevel: 0, propList: NIL]
Normal Char:
[charSet: 0, char: 'F, looks: LOOKS[], format: $code, comment: FALSE, endOfNode: FALSE, deltaLevel: 0, propList: NIL]
Comment end of node (next node nested):
[charSet: 0, char: '\n, looks: LOOKS[], format: $code, comment: TRUE, endOfNode: TRUE, deltaLevel: 1, propList: NIL]
{
tc: TiogaAccess.TiogaChar ← [
charSet: 0,
char: '\n,
looks: ALL[FALSE],
format: NIL,
comment: FALSE,
endOfNode: TRUE,
deltaLevel: 1,
propList: List.PutAssoc[key: $FromTiogaFile, val: $Yes, aList: NIL]
];
PutRope:
PROC [rope:
ROPE] = {
[] ← Rope.Map[base: rope, action: PutCharB];
};
PutRopeBold:
PROC [rope:
ROPE] = {
tc.looks['b] ← TRUE;
[] ← Rope.Map[base: rope, action: PutCharB];
tc.looks['b] ← FALSE;
};
PutRopeItalic:
PROC [rope:
ROPE] = {
tc.looks['i] ← TRUE;
[] ← Rope.Map[base: rope, action: PutCharB];
tc.looks['i] ← FALSE;
};
PutCharB: Rope.ActionType = {
[c: CHAR] RETURNS [quit: BOOL ← FALSE]
tc.char ← c;
TiogaAccess.Put[writer, tc];
};
EndNode:
PROC [delta:
INTEGER ← 0, format:
ATOM ←
NIL] = {
tc.endOfNode ← TRUE;
tc.char ← '\n;
tc.format ← format;
tc.deltaLevel ← delta;
TiogaAccess.Put[writer, tc];
tc.endOfNode ← FALSE;
};
eachNode: RedBlackTree.EachNode = {
[data: RedBlackTree.UserData] RETURNS [stop: BOOL ← FALSE]
WITH data
SELECT
FROM
base: BaseEntry =>
WHILE base #
NIL
DO
dependents: BaseEntryList ← base.dependents ← SortDependents[base.dependents];
SELECT
TRUE
FROM
dependents = NIL AND NOT switches['u] => {};
base.from = NIL AND NOT switches['v] => {};
ENDCASE => {
tc.format ← $block;
PutRopeBold[base.name];
PutRope[": "];
PutRopeItalic["("];
IF base.from =
NIL
THEN PutRopeItalic["??"]
ELSE PutRopeItalic[base.from];
PutRopeItalic[")"];
EndNode[1, $block];
tc.format ← $block;
WHILE dependents #
NIL
DO
PutRope[dependents.first.name];
PutRope[" "];
dependents ← dependents.rest;
ENDLOOP;
EndNode[-1, $indent];
};
IF Rope.Match[suspectTo, base.name, FALSE] THEN SIGNAL SuspectSeen;
base ← base.next;
ENDLOOP;
ENDCASE;
};
writer: TiogaAccess.Writer ← TiogaAccess.Create[];
TiogaAccess.Put[writer, tc];
tc.comment ← TRUE;
tc.endOfNode ← FALSE;
tc.propList ← NIL;
PutRope[outName];
EndNode[];
EndNode[];
tc.comment ← FALSE;
IO.PutF1[out, "Writing dependencies to %g", [rope[outName]] ];
RedBlackTree.EnumerateIncreasing[table, eachNode];
TiogaAccess.WriteFile[writer, outName];
IO.PutRope[out, ".\n"];
};
};
argv: CommandTool.ArgumentVector ← CommandTool.Parse[cmd: cmd, starExpand:
FALSE
! CommandTool.Failed => {msg ← errorMsg; GO TO failed}];
When parsing the command line, be prepared for failure. The error is reported to the user
FOR i:
NAT
IN [1..argv.argc)
DO
Each argument can either be a switch specification or a genuine argument to be processed. The first argument (argv[0]) is not examined, because by convention it is the name of the command as given by the user.
arg: ROPE = argv[i];
Process.CheckForAbort[];
It is a good idea to periodically check for a process abort request.
IF Rope.Length[arg] = 0
THEN
LOOP;
Ignore null arguments (it is not easy to generate them, even).
IF Rope.Fetch[arg, 0] = '-
THEN {
This argument sets switches for the remaining patterns. By convention, switches are normally "sticky", in that they stay set until explicitly changed.
ProcessSwitches[arg];
LOOP;
};
ProcessArgument[arg];
Perform whatever processing is necessary for a normal argument.
ENDLOOP;