DEADSOFTWARE

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