CPMake.cp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. (***********************************************************************)
  2. (* Component Pascal Make Tool *)
  3. (* *)
  4. (* Diane Corney, 20th July 1999 *)
  5. (* Modifications: *)
  6. (* *)
  7. (* *)
  8. (***********************************************************************)
  9. MODULE CPMake ;
  10. IMPORT GPCPcopyright,
  11. CPmain,
  12. CPascal,
  13. G := CPascalG,
  14. S := CPascalS,
  15. CPascalErrors,
  16. LitValue,
  17. ForeignName,
  18. GPFiles,
  19. GPBinFiles,
  20. GPTextFiles,
  21. NameHash,
  22. CompState,
  23. NewSymFileRW,
  24. MH := ModuleHandler,
  25. SF := SymbolFile,
  26. ProgArgs,
  27. FileNames,
  28. Error,
  29. RTS,
  30. Console;
  31. TYPE
  32. ArgString = ARRAY 256 OF CHAR;
  33. ArgBlock = RECORD
  34. args : POINTER TO ARRAY OF ArgString;
  35. argNum : INTEGER;
  36. END;
  37. CONST
  38. argSize = 10;
  39. VAR
  40. startT, endT : LONGINT;
  41. VAR
  42. toDoList, compList : MH.ModList;
  43. graph : MH.ModInfo;
  44. token : S.Token;
  45. sysBkt : INTEGER;
  46. frnBkt : INTEGER;
  47. buildOK : BOOLEAN;
  48. compCount : INTEGER;
  49. args : ArgBlock;
  50. force : BOOLEAN;
  51. PROCEDURE Chuck(IN msg : ARRAY OF CHAR);
  52. BEGIN
  53. Error.WriteString('CPMake: "');
  54. Error.WriteString(msg);
  55. Error.WriteString('" Halting...');
  56. Error.WriteLn; HALT(1);
  57. END Chuck;
  58. PROCEDURE Warn(IN msg : ARRAY OF CHAR);
  59. BEGIN
  60. Console.WriteString('CPMake: ');
  61. Console.WriteString(msg); Console.WriteLn;
  62. END Warn;
  63. PROCEDURE Usage();
  64. CONST jPre = "cprun ";
  65. str1 = "Usage: CPMake [";
  66. str2 = "all] [gpcp-options] <ModuleName>";
  67. str3 = " For gpcp-options, type: ";
  68. str4 = "gpcp ";
  69. str5 = "help";
  70. VAR isNt : BOOLEAN;
  71. BEGIN
  72. Console.WriteString("gardens point CPMake: " + GPCPcopyright.verStr);
  73. Console.WriteLn;
  74. isNt := RTS.defaultTarget = "net";
  75. IF ~isNt THEN Console.WriteString(jPre) END;
  76. Console.WriteString(str1);
  77. Console.Write(GPFiles.optChar);
  78. Console.WriteString(str2);
  79. Console.WriteLn();
  80. Console.WriteString(str3);
  81. IF ~isNt THEN Console.WriteString(jPre) END;
  82. Console.WriteString(str4);
  83. Console.Write(GPFiles.optChar);
  84. Console.WriteString(str5);
  85. Console.WriteLn();
  86. END Usage;
  87. PROCEDURE ReadModuleName(VAR name : ARRAY OF CHAR);
  88. VAR
  89. i, pos, parNum, numArgs : INTEGER;
  90. opt : ArgString;
  91. BEGIN
  92. numArgs := ProgArgs.ArgNumber();
  93. args.argNum := 0;
  94. CompState.InitOptions();
  95. IF numArgs < 1 THEN
  96. Usage();
  97. HALT(1);
  98. END;
  99. IF numArgs > 1 THEN
  100. NEW(args.args, numArgs-1);
  101. FOR parNum := 0 TO numArgs-2 DO
  102. ProgArgs.GetArg(parNum,opt);
  103. IF (opt[0] = '-') OR (opt[0] = GPFiles.optChar) THEN
  104. opt[0] := '-';
  105. IF opt = "-all" THEN
  106. force := TRUE;
  107. ELSE
  108. CPascal.DoOption(opt);
  109. args.args[args.argNum] := opt;
  110. INC(args.argNum);
  111. END;
  112. ELSE
  113. Console.WriteString("Unknown option: " + opt);
  114. Console.WriteLn;
  115. END;
  116. END;
  117. END;
  118. ProgArgs.GetArg(numArgs-1,name);
  119. IF (name[0] = '-') OR (name[0] = GPFiles.optChar) THEN
  120. Usage();
  121. HALT(1);
  122. END;
  123. i := 0;
  124. WHILE (name[i] # '.') & (name[i] # 0X) & (i < LEN(name)) DO INC(i); END;
  125. IF (i < LEN(name)) & (name[i] = '.') THEN
  126. WHILE (name[i] # 0X) & (i < LEN(name)) DO
  127. name[i] := 0X; INC(i);
  128. END;
  129. END;
  130. END ReadModuleName;
  131. PROCEDURE Check (sym : INTEGER; mod : MH.ModInfo);
  132. BEGIN
  133. IF token.sym # sym THEN
  134. S.ParseErr.Report(sym,token.lin,token.col);
  135. GPBinFiles.CloseFile(S.src);
  136. CPascal.FixListing();
  137. CPascal.Finalize();
  138. Chuck("Parse error(s) in module <" + mod.name + ">");
  139. END;
  140. END Check;
  141. PROCEDURE DoImport(mod : MH.ModInfo; VAR mainImported : BOOLEAN);
  142. VAR
  143. mName : FileNames.NameString;
  144. aMod : MH.ModInfo;
  145. last : S.Token;
  146. strng, impNm : POINTER TO ARRAY OF CHAR;
  147. (* ----------------------------------------------------------- *)
  148. PROCEDURE AssignOpen(src : LitValue.CharOpen;
  149. OUT dst : FileNames.NameString);
  150. VAR idx, max : INTEGER;
  151. BEGIN
  152. max := MIN(LEN(src), LEN(FileNames.NameString));
  153. FOR idx := 0 TO max-1 DO dst[idx] := src[idx] END;
  154. END AssignOpen;
  155. (* ----------------------------------------------------------- *)
  156. BEGIN
  157. Check(G.identSym,mod);
  158. last := token;
  159. token := S.get(); (* read past ident *)
  160. IF (token.sym = G.colonequalSym) THEN
  161. last := S.get(); (* read past ":=" *)
  162. token := S.get(); (* read past ident *)
  163. END;
  164. IF last.sym = G.identSym THEN
  165. S.GetString(last.pos, last.len, mName);
  166. ELSIF last.sym = G.stringSym THEN
  167. strng := LitValue.subStrToCharOpen(last.pos+1, last.len-2);
  168. ForeignName.ParseModuleString(strng, impNm);
  169. AssignOpen(impNm, mName);
  170. ELSE
  171. Chuck("Bad module name for alias import");
  172. END;
  173. IF (NameHash.enterSubStr(last.pos, last.len) = NameHash.mainBkt) OR
  174. (NameHash.enterSubStr(last.pos, last.len) = NameHash.winMain) THEN
  175. mainImported := TRUE;
  176. ELSE
  177. aMod := MH.GetModule(mName);
  178. MH.Add(mod.imports,aMod);
  179. MH.Add(aMod.importedBy,mod);
  180. IF ~aMod.importsLinked THEN MH.Add(toDoList,aMod); END;
  181. END;
  182. END DoImport;
  183. PROCEDURE LinkImports(mod : MH.ModInfo);
  184. VAR
  185. mName : FileNames.NameString;
  186. cpmainImported : BOOLEAN;
  187. hsh : INTEGER;
  188. BEGIN
  189. CompState.InitCompState(mod.name + ".cp");
  190. mod.importsLinked := TRUE;
  191. cpmainImported := FALSE;
  192. S.Reset;
  193. token := S.get();
  194. IF (token.sym = G.identSym) THEN
  195. hsh := NameHash.enterSubStr(token.pos,token.len);
  196. IF (hsh = sysBkt) OR (hsh = frnBkt) THEN
  197. mod.isForeign := TRUE;
  198. token := S.get();
  199. END;
  200. END;
  201. Check(G.MODULESym,mod); token := S.get();
  202. Check(G.identSym,mod);
  203. S.GetString(token.pos,token.len,mName);
  204. IF (mName # mod.name) THEN
  205. Chuck("File " + mod.name + ".cp does not contain MODULE " + mName);
  206. END;
  207. token := S.get();
  208. IF token.sym = G.lbrackSym THEN
  209. (* mod.isForeign := TRUE; *)
  210. token := S.get(); (* skip string and rbracket *)
  211. token := S.get();
  212. token := S.get();
  213. END;
  214. Check(G.semicolonSym,mod); token := S.get();
  215. IF (token.sym = G.IMPORTSym) THEN
  216. token := S.get();
  217. DoImport(mod,cpmainImported);
  218. WHILE (token.sym = G.commaSym) DO
  219. token := S.get();
  220. DoImport(mod,cpmainImported);
  221. END;
  222. END;
  223. IF (mod = graph) & ~cpmainImported THEN
  224. Warn("WARNING: " + mod.name + " is not a base module.");
  225. Warn("Modules that " + mod.name + " depends on will be checked for consistency");
  226. Warn("Modules that depend on " + mod.name + " will not be checked or recompiled");
  227. END;
  228. END LinkImports;
  229. PROCEDURE BuildGraph() : BOOLEAN;
  230. VAR
  231. name : FileNames.NameString;
  232. nextIx : INTEGER;
  233. nextModule : MH.ModInfo;
  234. srcFound : BOOLEAN;
  235. BEGIN
  236. NEW(graph);
  237. ReadModuleName(name);
  238. graph := MH.GetModule(name);
  239. S.src := GPBinFiles.findLocal(graph.name + ".cp");
  240. IF S.src = NIL THEN
  241. Chuck("Could not find base file <" + graph.name + ".cp>");
  242. ELSE
  243. GPBinFiles.CloseFile(S.src);
  244. END;
  245. MH.Add(toDoList,graph);
  246. nextIx := 0;
  247. WHILE (nextIx < toDoList.tide) DO
  248. nextModule := toDoList.list[nextIx]; INC(nextIx);
  249. S.src := GPBinFiles.findLocal(nextModule.name + ".cp");
  250. SF.OpenSymbolFile(nextModule.name, S.src = NIL);
  251. IF S.src = NIL THEN
  252. IF SF.file = NIL THEN
  253. Chuck("Cannot find source file <" + nextModule.name +
  254. ".cp> or symbol file <" + nextModule.name +
  255. ".cps> on CPSYM path.");
  256. ELSE
  257. SF.ReadSymbolFile(nextModule,FALSE);
  258. END ;
  259. ELSE
  260. LinkImports(nextModule);
  261. IF force OR (SF.file = NIL) OR ~GPFiles.isOlder(S.src,SF.file) THEN
  262. nextModule.compile := TRUE;
  263. (*
  264. * IF force THEN
  265. * Console.WriteString("force: Setting compile flag on ");
  266. * Console.WriteString(nextModule.name);
  267. * Console.WriteLn;
  268. * ELSIF (SF.file = NIL) THEN
  269. * Console.WriteString("file=NIL: Setting compile flag on ");
  270. * Console.WriteString(nextModule.name);
  271. * Console.WriteLn;
  272. * ELSIF ~GPFiles.isOlder(S.src,SF.file) THEN
  273. * Console.WriteString("isOlder: Setting compile flag on ");
  274. * Console.WriteString(nextModule.name);
  275. * Console.WriteLn;
  276. * END;
  277. *)
  278. ELSE
  279. SF.ReadSymbolFile(nextModule,TRUE);
  280. END;
  281. SF.CloseSymFile(); (* or .NET barfs! *)
  282. END;
  283. END;
  284. RETURN TRUE;
  285. RESCUE (buildX)
  286. Console.WriteString("#cpmake: ");
  287. Console.WriteString(RTS.getStr(buildX));
  288. Console.WriteLn;
  289. RETURN FALSE;
  290. END BuildGraph;
  291. PROCEDURE CompileModule(mod : MH.ModInfo; VAR retVal : INTEGER);
  292. VAR
  293. i : INTEGER;
  294. BEGIN
  295. CompState.InitOptions();
  296. FOR i := 0 TO args.argNum-1 DO
  297. CPascal.DoOption(args.args[i]);
  298. END;
  299. IF mod.isForeign THEN
  300. IF ~CompState.quiet THEN
  301. Console.WriteString(
  302. "#cpmake: "+mod.name+" is foreign, compiling with -special.");
  303. Console.WriteLn;
  304. Console.WriteString(
  305. "#cpmake: Foreign implementation may need recompilation.");
  306. Console.WriteLn;
  307. END;
  308. CPascal.DoOption("-special");
  309. ELSIF ~CompState.quiet THEN
  310. Console.WriteString("#cpmake: compiling " + mod.name);
  311. Console.WriteLn;
  312. END;
  313. CPascal.Compile(mod.name+".cp",retVal);
  314. mod.key := NewSymFileRW.GetLastKeyVal();
  315. INC(compCount);
  316. END CompileModule;
  317. PROCEDURE DFS(VAR node : MH.ModInfo);
  318. VAR
  319. ix,retVal : INTEGER;
  320. imp : MH.ModInfo;
  321. BEGIN
  322. IF ~node.done THEN
  323. node.done := TRUE;
  324. FOR ix := 0 TO node.imports.tide-1 DO
  325. DFS(node.imports.list[ix]);
  326. END;
  327. IF node.compile THEN
  328. retVal := 0;
  329. CompileModule(node,retVal);
  330. IF retVal # 0 THEN
  331. Chuck("Compile errors in module <" + node.name + ">");
  332. END;
  333. END;
  334. FOR ix := 0 TO node.importedBy.tide-1 DO
  335. imp := node.importedBy.list[ix];
  336. IF (~imp.compile) & (node.key # MH.GetKey(imp,node)) THEN
  337. node.importedBy.list[ix].compile := TRUE;
  338. END;
  339. END;
  340. END;
  341. END DFS;
  342. PROCEDURE WalkGraph(VAR node : MH.ModInfo);
  343. BEGIN
  344. DFS(node);
  345. RESCUE (compX)
  346. Console.WriteString("#cpmake: ");
  347. Console.WriteString(RTS.getStr(compX));
  348. Console.WriteLn;
  349. END WalkGraph;
  350. BEGIN
  351. force := FALSE;
  352. compCount := 0;
  353. NameHash.InitNameHash(0);
  354. sysBkt := NameHash.enterStr("SYSTEM");
  355. frnBkt := NameHash.enterStr("FOREIGN");
  356. CPascalErrors.Init();
  357. buildOK := BuildGraph();
  358. IF buildOK THEN
  359. startT := RTS.GetMillis();
  360. WalkGraph(graph);
  361. endT := RTS.GetMillis();
  362. Console.WriteString("#cpmake: ");
  363. IF compCount = 0 THEN
  364. Console.WriteString("no re-compilation required.");
  365. ELSIF compCount = 1 THEN
  366. Console.WriteString("one module compiled.");
  367. ELSE
  368. Console.WriteInt(compCount,1);
  369. Console.WriteString(" modules compiled.");
  370. END;
  371. Console.WriteLn;
  372. CompState.TimeMsg("Total Compilation Time ", endT - startT);
  373. END;
  374. END CPMake.