123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391 |
- (***********************************************************************)
- (* Component Pascal Make Tool *)
- (* *)
- (* Diane Corney, 20th July 1999 *)
- (* Modifications: *)
- (* *)
- (* *)
- (***********************************************************************)
- MODULE CPMake ;
- IMPORT GPCPcopyright,
- CPmain,
- CPascal,
- G := CPascalG,
- S := CPascalS,
- CPascalErrors,
- LitValue,
- ForeignName,
- GPFiles,
- GPBinFiles,
- GPTextFiles,
- NameHash,
- CompState,
- NewSymFileRW,
- MH := ModuleHandler,
- SF := SymbolFile,
- ProgArgs,
- FileNames,
- Error,
- RTS,
- Console;
- TYPE
- ArgString = ARRAY 256 OF CHAR;
- ArgBlock = RECORD
- args : POINTER TO ARRAY OF ArgString;
- argNum : INTEGER;
- END;
- CONST
- argSize = 10;
- VAR
- startT, endT : LONGINT;
- VAR
- toDoList, compList : MH.ModList;
- graph : MH.ModInfo;
- token : S.Token;
- sysBkt : INTEGER;
- frnBkt : INTEGER;
- buildOK : BOOLEAN;
- compCount : INTEGER;
- args : ArgBlock;
- force : BOOLEAN;
- PROCEDURE Chuck(IN msg : ARRAY OF CHAR);
- BEGIN
- Error.WriteString('CPMake: "');
- Error.WriteString(msg);
- Error.WriteString('" Halting...');
- Error.WriteLn; HALT(1);
- END Chuck;
- PROCEDURE Warn(IN msg : ARRAY OF CHAR);
- BEGIN
- Console.WriteString('CPMake: ');
- Console.WriteString(msg); Console.WriteLn;
- END Warn;
- PROCEDURE Usage();
- CONST jPre = "cprun ";
- str1 = "Usage: CPMake [";
- str2 = "all] [gpcp-options] <ModuleName>";
- str3 = " For gpcp-options, type: ";
- str4 = "gpcp ";
- str5 = "help";
- VAR isNt : BOOLEAN;
- BEGIN
- Console.WriteString("gardens point CPMake: " + GPCPcopyright.verStr);
- Console.WriteLn;
- isNt := RTS.defaultTarget = "net";
- IF ~isNt THEN Console.WriteString(jPre) END;
- Console.WriteString(str1);
- Console.Write(GPFiles.optChar);
- Console.WriteString(str2);
- Console.WriteLn();
- Console.WriteString(str3);
- IF ~isNt THEN Console.WriteString(jPre) END;
- Console.WriteString(str4);
- Console.Write(GPFiles.optChar);
- Console.WriteString(str5);
- Console.WriteLn();
- END Usage;
- PROCEDURE ReadModuleName(VAR name : ARRAY OF CHAR);
- VAR
- i, pos, parNum, numArgs : INTEGER;
- opt : ArgString;
- BEGIN
- numArgs := ProgArgs.ArgNumber();
- args.argNum := 0;
- CompState.InitOptions();
- IF numArgs < 1 THEN
- Usage();
- HALT(1);
- END;
- IF numArgs > 1 THEN
- NEW(args.args, numArgs-1);
- FOR parNum := 0 TO numArgs-2 DO
- ProgArgs.GetArg(parNum,opt);
- IF (opt[0] = '-') OR (opt[0] = GPFiles.optChar) THEN
- opt[0] := '-';
- IF opt = "-all" THEN
- force := TRUE;
- ELSE
- CPascal.DoOption(opt);
- args.args[args.argNum] := opt;
- INC(args.argNum);
- END;
- ELSE
- Console.WriteString("Unknown option: " + opt);
- Console.WriteLn;
- END;
- END;
- END;
- ProgArgs.GetArg(numArgs-1,name);
- IF (name[0] = '-') OR (name[0] = GPFiles.optChar) THEN
- Usage();
- HALT(1);
- END;
- i := 0;
- WHILE (name[i] # '.') & (name[i] # 0X) & (i < LEN(name)) DO INC(i); END;
- IF (i < LEN(name)) & (name[i] = '.') THEN
- WHILE (name[i] # 0X) & (i < LEN(name)) DO
- name[i] := 0X; INC(i);
- END;
- END;
- END ReadModuleName;
- PROCEDURE Check (sym : INTEGER; mod : MH.ModInfo);
- BEGIN
- IF token.sym # sym THEN
- S.ParseErr.Report(sym,token.lin,token.col);
- GPBinFiles.CloseFile(S.src);
- CPascal.FixListing();
- CPascal.Finalize();
- Chuck("Parse error(s) in module <" + mod.name + ">");
- END;
- END Check;
- PROCEDURE DoImport(mod : MH.ModInfo; VAR mainImported : BOOLEAN);
- VAR
- mName : FileNames.NameString;
- aMod : MH.ModInfo;
- last : S.Token;
- strng, impNm : POINTER TO ARRAY OF CHAR;
- (* ----------------------------------------------------------- *)
- PROCEDURE AssignOpen(src : LitValue.CharOpen;
- OUT dst : FileNames.NameString);
- VAR idx, max : INTEGER;
- BEGIN
- max := MIN(LEN(src), LEN(FileNames.NameString));
- FOR idx := 0 TO max-1 DO dst[idx] := src[idx] END;
- END AssignOpen;
- (* ----------------------------------------------------------- *)
- BEGIN
- Check(G.identSym,mod);
- last := token;
- token := S.get(); (* read past ident *)
- IF (token.sym = G.colonequalSym) THEN
- last := S.get(); (* read past ":=" *)
- token := S.get(); (* read past ident *)
- END;
- IF last.sym = G.identSym THEN
- S.GetString(last.pos, last.len, mName);
- ELSIF last.sym = G.stringSym THEN
- strng := LitValue.subStrToCharOpen(last.pos+1, last.len-2);
- ForeignName.ParseModuleString(strng, impNm);
- AssignOpen(impNm, mName);
- ELSE
- Chuck("Bad module name for alias import");
- END;
- IF (NameHash.enterSubStr(last.pos, last.len) = NameHash.mainBkt) OR
- (NameHash.enterSubStr(last.pos, last.len) = NameHash.winMain) THEN
- mainImported := TRUE;
- ELSE
- aMod := MH.GetModule(mName);
- MH.Add(mod.imports,aMod);
- MH.Add(aMod.importedBy,mod);
- IF ~aMod.importsLinked THEN MH.Add(toDoList,aMod); END;
- END;
- END DoImport;
- PROCEDURE LinkImports(mod : MH.ModInfo);
- VAR
- mName : FileNames.NameString;
- cpmainImported : BOOLEAN;
- hsh : INTEGER;
- BEGIN
- CompState.InitCompState(mod.name + ".cp");
- mod.importsLinked := TRUE;
- cpmainImported := FALSE;
- S.Reset;
- token := S.get();
- IF (token.sym = G.identSym) THEN
- hsh := NameHash.enterSubStr(token.pos,token.len);
- IF (hsh = sysBkt) OR (hsh = frnBkt) THEN
- mod.isForeign := TRUE;
- token := S.get();
- END;
- END;
- Check(G.MODULESym,mod); token := S.get();
- Check(G.identSym,mod);
- S.GetString(token.pos,token.len,mName);
- IF (mName # mod.name) THEN
- Chuck("File " + mod.name + ".cp does not contain MODULE " + mName);
- END;
- token := S.get();
- IF token.sym = G.lbrackSym THEN
- (* mod.isForeign := TRUE; *)
- token := S.get(); (* skip string and rbracket *)
- token := S.get();
- token := S.get();
- END;
- Check(G.semicolonSym,mod); token := S.get();
- IF (token.sym = G.IMPORTSym) THEN
- token := S.get();
- DoImport(mod,cpmainImported);
- WHILE (token.sym = G.commaSym) DO
- token := S.get();
- DoImport(mod,cpmainImported);
- END;
- END;
- IF (mod = graph) & ~cpmainImported THEN
- Warn("WARNING: " + mod.name + " is not a base module.");
- Warn("Modules that " + mod.name + " depends on will be checked for consistency");
- Warn("Modules that depend on " + mod.name + " will not be checked or recompiled");
- END;
- END LinkImports;
- PROCEDURE BuildGraph() : BOOLEAN;
- VAR
- name : FileNames.NameString;
- nextIx : INTEGER;
- nextModule : MH.ModInfo;
- srcFound : BOOLEAN;
- BEGIN
- NEW(graph);
- ReadModuleName(name);
- graph := MH.GetModule(name);
- S.src := GPBinFiles.findLocal(graph.name + ".cp");
- IF S.src = NIL THEN
- Chuck("Could not find base file <" + graph.name + ".cp>");
- ELSE
- GPBinFiles.CloseFile(S.src);
- END;
- MH.Add(toDoList,graph);
- nextIx := 0;
- WHILE (nextIx < toDoList.tide) DO
- nextModule := toDoList.list[nextIx]; INC(nextIx);
- S.src := GPBinFiles.findLocal(nextModule.name + ".cp");
- SF.OpenSymbolFile(nextModule.name, S.src = NIL);
- IF S.src = NIL THEN
- IF SF.file = NIL THEN
- Chuck("Cannot find source file <" + nextModule.name +
- ".cp> or symbol file <" + nextModule.name +
- ".cps> on CPSYM path.");
- ELSE
- SF.ReadSymbolFile(nextModule,FALSE);
- END ;
- ELSE
- LinkImports(nextModule);
- IF force OR (SF.file = NIL) OR ~GPFiles.isOlder(S.src,SF.file) THEN
- nextModule.compile := TRUE;
- (*
- * IF force THEN
- * Console.WriteString("force: Setting compile flag on ");
- * Console.WriteString(nextModule.name);
- * Console.WriteLn;
- * ELSIF (SF.file = NIL) THEN
- * Console.WriteString("file=NIL: Setting compile flag on ");
- * Console.WriteString(nextModule.name);
- * Console.WriteLn;
- * ELSIF ~GPFiles.isOlder(S.src,SF.file) THEN
- * Console.WriteString("isOlder: Setting compile flag on ");
- * Console.WriteString(nextModule.name);
- * Console.WriteLn;
- * END;
- *)
- ELSE
- SF.ReadSymbolFile(nextModule,TRUE);
- END;
- SF.CloseSymFile(); (* or .NET barfs! *)
- END;
- END;
- RETURN TRUE;
- RESCUE (buildX)
- Console.WriteString("#cpmake: ");
- Console.WriteString(RTS.getStr(buildX));
- Console.WriteLn;
- RETURN FALSE;
- END BuildGraph;
- PROCEDURE CompileModule(mod : MH.ModInfo; VAR retVal : INTEGER);
- VAR
- i : INTEGER;
- BEGIN
- CompState.InitOptions();
- FOR i := 0 TO args.argNum-1 DO
- CPascal.DoOption(args.args[i]);
- END;
- IF mod.isForeign THEN
- IF ~CompState.quiet THEN
- Console.WriteString(
- "#cpmake: "+mod.name+" is foreign, compiling with -special.");
- Console.WriteLn;
- Console.WriteString(
- "#cpmake: Foreign implementation may need recompilation.");
- Console.WriteLn;
- END;
- CPascal.DoOption("-special");
- ELSIF ~CompState.quiet THEN
- Console.WriteString("#cpmake: compiling " + mod.name);
- Console.WriteLn;
- END;
- CPascal.Compile(mod.name+".cp",retVal);
- mod.key := NewSymFileRW.GetLastKeyVal();
- INC(compCount);
- END CompileModule;
- PROCEDURE DFS(VAR node : MH.ModInfo);
- VAR
- ix,retVal : INTEGER;
- imp : MH.ModInfo;
- BEGIN
- IF ~node.done THEN
- node.done := TRUE;
- FOR ix := 0 TO node.imports.tide-1 DO
- DFS(node.imports.list[ix]);
- END;
- IF node.compile THEN
- retVal := 0;
- CompileModule(node,retVal);
- IF retVal # 0 THEN
- Chuck("Compile errors in module <" + node.name + ">");
- END;
- END;
- FOR ix := 0 TO node.importedBy.tide-1 DO
- imp := node.importedBy.list[ix];
- IF (~imp.compile) & (node.key # MH.GetKey(imp,node)) THEN
- node.importedBy.list[ix].compile := TRUE;
- END;
- END;
- END;
- END DFS;
- PROCEDURE WalkGraph(VAR node : MH.ModInfo);
- BEGIN
- DFS(node);
- RESCUE (compX)
- Console.WriteString("#cpmake: ");
- Console.WriteString(RTS.getStr(compX));
- Console.WriteLn;
- END WalkGraph;
- BEGIN
- force := FALSE;
- compCount := 0;
- NameHash.InitNameHash(0);
- sysBkt := NameHash.enterStr("SYSTEM");
- frnBkt := NameHash.enterStr("FOREIGN");
- CPascalErrors.Init();
- buildOK := BuildGraph();
- IF buildOK THEN
- startT := RTS.GetMillis();
- WalkGraph(graph);
- endT := RTS.GetMillis();
- Console.WriteString("#cpmake: ");
- IF compCount = 0 THEN
- Console.WriteString("no re-compilation required.");
- ELSIF compCount = 1 THEN
- Console.WriteString("one module compiled.");
- ELSE
- Console.WriteInt(compCount,1);
- Console.WriteString(" modules compiled.");
- END;
- Console.WriteLn;
- CompState.TimeMsg("Total Compilation Time ", endT - startT);
- END;
- END CPMake.
|