DEADSOFTWARE

b88795d846777093012fcf5ba61934780c18ff28
[cpc.git] / src / generic / Dsw / Mod / MakeMain.cp
1 MODULE DswMakeMain;
3 IMPORT Kernel, Files, Log, Strings, DswOpts, DswProcs, DswDocuments, DevCPM, DevCPT, DevCPR, DevCPS;
5 CONST
6 version = "0.3";
8 modDir = "Mod";
9 sysDir = "System";
11 maxImps = 127;
12 maxJobs = maxImps;
14 (* symbol values *)
15 null = 0; times = 1; slash = 2; div = 3; mod = 4;
16 and = 5; plus = 6; minus = 7; or = 8; eql = 9;
17 neq = 10; lss = 11; leq = 12; gtr = 13; geq = 14;
18 in = 15; is = 16; arrow = 17; dollar = 18; period = 19;
19 comma = 20; colon = 21; upto = 22; rparen = 23; rbrak = 24;
20 rbrace = 25; of = 26; then = 27; do = 28; to = 29;
21 by = 30; not = 33;
22 lparen = 40; lbrak = 41; lbrace = 42; becomes = 44;
23 number = 45; nil = 46; string = 47; ident = 48; semicolon = 49;
24 bar = 50; end = 51; else = 52; elsif = 53; until = 54;
25 if = 55; case = 56; while = 57; repeat = 58; for = 59;
26 loop = 60; with = 61; exit = 62; return = 63; array = 64;
27 record = 65; pointer = 66; begin = 67; const = 68; type = 69;
28 var = 70; out = 71; procedure = 72; close = 73; import = 74;
29 module = 75; eof = 76;
31 (* module state flags *)
32 imported = 0; trace = 1; hasObj = 2; hasSym = 3; hasErrors = 4;
33 library = 5; force = 6;
35 debugImport = FALSE;
36 debugOrder = FALSE;
37 debugJobs = FALSE;
39 TYPE
40 Name = ARRAY 256 OF CHAR;
42 String = POINTER TO ARRAY OF CHAR;
44 Selector = POINTER TO RECORD
45 name: DevCPT.Name;
46 value: BOOLEAN;
47 next: Selector
48 END;
50 Module = POINTER TO RECORD
51 name: DevCPT.Name;
52 library: DevCPT.Name;
53 odc: Files.Name;
54 depth: INTEGER; (* 0: leaf, MAX: root *)
55 dir: DevCPM.Directory;
56 mno: INTEGER;
57 imp: ARRAY maxImps OF Module;
58 flags: SET;
59 worker: DswProcs.Process;
60 END;
62 Library = POINTER TO RECORD
63 name: Name;
64 library: Name;
65 next: Library;
66 END;
68 VAR (* options *)
69 auto, trap, clean, symonly, nocode1, nocode2: BOOLEAN;
70 exe, target, base: String;
71 jobs: INTEGER;
73 VAR
74 werr, err: INTEGER;
75 mno, rno: INTEGER; (* num modules *)
76 modList, lnkList, cmpList: ARRAY maxImps OF Module;
77 def: Selector; (* with head, global list of selectors *)
78 dirList: DevCPM.Directory;
79 libList: Library;
81 PROCEDURE Error (IN str, p0, p1: ARRAY OF CHAR; i2: INTEGER);
82 VAR p2: ARRAY 32 OF CHAR;
83 BEGIN
84 Strings.IntToString(i2, p2);
85 Log.String("cpmake: "); Log.ParamMsg(str, p0, p1, p2); Log.Ln;
86 INC(err);
87 IF trap THEN
88 HALT(100)
89 END
90 END Error;
92 (* --------- options --------- *)
94 PROCEDURE IdentLen (IN s: ARRAY OF CHAR): INTEGER;
95 VAR i: INTEGER;
96 BEGIN
97 i := 0;
98 IF Strings.IsIdentStart(s[0]) THEN
99 REPEAT INC(i) UNTIL ~Strings.IsIdent(s[i])
100 END;
101 RETURN i
102 END IdentLen;
104 PROCEDURE Define (n: ARRAY OF CHAR; overwrite: BOOLEAN);
105 VAR i: INTEGER; v: BOOLEAN; s: Selector;
106 BEGIN
107 i := IdentLen(n);
108 IF i # 0 THEN
109 IF ~((n[i] = 0X) OR (((n[i] = "+") OR (n[i] = "-")) & (n[i + 1] = 0X))) THEN
110 Error("expectd + or - after selector identifier (^0)", n, "", 0)
111 END;
112 v := n[i] # "-"; n[i] := 0X; s := def;
113 WHILE (s.next # NIL) & (s.next.name$ # n$) DO s := s.next END;
114 IF s.next = NIL THEN
115 NEW(s.next);
116 Strings.StringToUtf8(n, s.next.name, i);
117 ASSERT(i = 0);
118 s.next.value := v
119 ELSIF overwrite THEN
120 s.next.value := v
121 END
122 ELSE Error("selector '^0' have invalid identifier", n, "", 0)
123 END
124 END Define;
126 PROCEDURE AddModule (IN n: ARRAY OF CHAR; selectors: Selector; dir: DevCPM.Directory);
127 VAR i, res: INTEGER; m: Module;
128 BEGIN
129 i := IdentLen(n);
130 IF (i # 0) & (n[i] = 0X) THEN
131 i := 0;
132 WHILE (i < mno) & (modList[i].name$ # n$) DO INC(i) END;
133 IF i >= mno THEN
134 NEW(m);
135 Strings.StringToUtf8(n, m.name, res);
136 ASSERT(res = 0);
137 m.dir := dir;
138 modList[i] := m;
139 INC(mno)
140 END
141 ELSE
142 Error("invalid module name", "", "", 0)
143 END
144 END AddModule;
146 PROCEDURE AddLibrary (IN key, val: ARRAY OF CHAR);
147 VAR x: Library;
148 BEGIN
149 x := libList;
150 WHILE (x # NIL) & (x.name$ # key$) DO x := x.next END;
151 IF x # NIL THEN x.library := val$
152 ELSE NEW(x); x.name := key$; x.library := val$; x.next := libList; libList := x
153 END
154 END AddLibrary;
156 PROCEDURE AddLib (IN s: ARRAY OF CHAR);
157 VAR key, val: Name; i, j: INTEGER;
158 BEGIN
159 i := 0; j := 0;
160 WHILE (s[i] # 0X) & (s[i] # "=") DO
161 key[j] := s[i];
162 INC(j);
163 INC(i)
164 END;
165 key[j] := 0X;
166 j := 0;
167 IF s[i] = "=" THEN
168 INC(i);
169 WHILE s[i] # 0X DO
170 val[j] := s[i];
171 INC(j);
172 INC(i)
173 END
174 END;
175 val[j] := 0X;
176 IF key # "" THEN AddLibrary(key, val)
177 ELSE Error("empty library key", "", "", 0)
178 END
179 END AddLib;
181 PROCEDURE FindLib (IN key: ARRAY OF CHAR): Library;
182 VAR x: Library;
183 BEGIN
184 x := libList;
185 WHILE (x # NIL) & (x.name$ # key$) DO x := x.next END;
186 RETURN x
187 END FindLib;
189 PROCEDURE StrToInt (IN s: ARRAY OF CHAR; def: INTEGER): INTEGER;
190 VAR x, res: INTEGER;
191 BEGIN
192 Strings.StringToInt(s, x, res);
193 IF res # 0 THEN
194 Error("invalid integer value", s, "", 0);
195 x := def
196 END;
197 RETURN x
198 END StrToInt;
200 PROCEDURE NewStr (IN s: ARRAY OF CHAR): String;
201 VAR p: String;
202 BEGIN
203 NEW(p, LEN(s$) + 1); p^ := s$;
204 RETURN p
205 END NewStr;
207 PROCEDURE Help;
208 BEGIN
209 Log.String("Usage: cpmake [options] module..."); Log.Ln;
210 Log.String("Options:"); Log.Ln;
211 Log.String(" -a Enable automatic dependency resolution"); Log.Ln;
212 Log.String(" -b Do not compile modules"); Log.Ln;
213 Log.String(" -x Do not link objects"); Log.Ln;
214 Log.String(" -c Remove all generated files"); Log.Ln;
215 Log.String(" -s Generate symbol files only"); Log.Ln;
216 Log.String(" -d selector Add selector"); Log.Ln;
217 Log.String(" -r lib[=s] Replace library name on link stage"); Log.Ln;
218 Log.String(" -t target Specify target rules"); Log.Ln;
219 Log.String(" -o file Generate object file"); Log.Ln;
220 Log.String(" -j num Specifies the number of jobs to run simultaneously"); Log.Ln;
221 Log.String(" -f path Specifies path to directory with targets"); Log.Ln;
222 Log.String(" -h Print help"); Log.Ln;
223 Log.String(" -v Print version"); Log.Ln;
224 Kernel.Quit(0)
225 END Help;
227 PROCEDURE ParseArgs;
228 BEGIN
229 exe := NIL; auto := FALSE; jobs := 1; def.next := NIL; mno := 0; rno := 0;
230 target := NewStr("default"); base := NewStr("cprules");
231 LOOP
232 CASE DswOpts.GetOpt("acbxd:sgGo:t:j:f:r:h") OF
233 | "a": auto := TRUE
234 | "b": nocode1 := TRUE
235 | "x": nocode2 := TRUE
236 | "c": clean := TRUE
237 | "g": trap := TRUE
238 | "G": Kernel.intTrap := TRUE
239 | "s": symonly := TRUE
240 | "f": base := DswOpts.str
241 | "d": Define(DswOpts.str, TRUE)
242 | "r": AddLib(DswOpts.str)
243 | "h": Help
244 | "j": jobs := MIN(MAX(StrToInt(DswOpts.str, 1), 1), maxJobs)
245 | "o": exe := DswOpts.str
246 | "t": target := DswOpts.str
247 | "v": Log.String(version); Log.Ln; Kernel.Quit(0)
248 | ":": Error("missing argument for option -^0", DswOpts.str, "", 0)
249 | "?": Error("unknown option -^0", DswOpts.str, "", 0)
250 | "$": AddModule(DswOpts.str, def, dirList)
251 | 00X: EXIT
252 END
253 END
254 END ParseArgs;
256 PROCEDURE ReadDefines;
257 VAR loc: Files.Locator; name: Files.Name; m: DswDocuments.Model; r: DswDocuments.Reader; i, res: INTEGER;
258 BEGIN
259 loc := Files.dir.This(base).This(target);
260 DswDocuments.Open(loc, "defines", m, res);
261 IF res = 0 THEN
262 r := m.NewReader(NIL);
263 r.SetPos(0);
264 r.Read;
265 WHILE ~r.eot DO
266 i := 0;
267 WHILE ~r.eot & (r.char <= 20X) DO r.Read END;
268 WHILE ~r.eot & (r.char > 20X) DO name[i] := r.char; r.Read; INC(i) END;
269 IF i # 0 THEN name[i] := 0X; Define(name, FALSE) END
270 END
271 END
272 END ReadDefines;
274 PROCEDURE CheckParams;
275 BEGIN
276 IF (exe # NIL) & (exe^ = "") THEN
277 Error("specified empty file name for exe", "", "", 0)
278 END;
279 IF target^ = "" THEN
280 Error("specified empty rule", "", "", 0)
281 END;
282 IF base^ = "" THEN
283 Error("specified empty path to cpmake rules", "", "", 0)
284 END;
285 ReadDefines
286 END CheckParams;
288 (* --------- loader --------- *)
290 PROCEDURE Import (m: Module; IN name: DevCPT.Name);
291 VAR i, j: INTEGER; imp: Module;
292 BEGIN
293 ASSERT(m # NIL, 20);
294 ASSERT(name # "", 21);
295 IF debugImport THEN Log.String(" import "); Log.String(name$) END;
296 IF name = "SYSTEM" THEN INCL(DevCPM.options, DevCPM.sysImp)
297 ELSIF name = "COM" THEN INCL(DevCPM.options, DevCPM.com)
298 ELSIF name = "JAVA" THEN INCL(DevCPM.options, DevCPM.java)
299 ELSE
300 IF debugImport THEN Log.Char(" ") END;
301 i := 0; (* find module in local list *)
302 WHILE (i < m.mno) & (m.imp[i].name$ # name$) DO INC(i) END;
303 IF i >= m.mno THEN
304 j := 0; (* find module in global list *)
305 WHILE (j < mno) & (modList[j].name$ # name$) DO INC(j) END;
306 IF j >= mno THEN
307 IF ~auto THEN
308 Log.String("module " + name + " required before " + m.name); Log.Ln; INC(werr)
309 END;
310 NEW(imp); imp.name := name$;
311 modList[mno] := imp; INC(mno)
312 ELSE
313 imp := modList[j]
314 END;
315 m.imp[m.mno] := imp; INC(m.mno)
316 ELSE DevCPM.err(1)
317 END
318 END;
319 IF debugImport THEN Log.Ln END;
320 END Import;
322 PROCEDURE ParseModule (m: Module);
323 VAR sym: BYTE; SelfName, impName, aliasName: DevCPT.Name;
325 PROCEDURE err (n: SHORTINT);
326 BEGIN DevCPM.err(n)
327 END err;
329 PROCEDURE CheckSym(s: SHORTINT);
330 BEGIN
331 IF sym = s THEN DevCPS.Get(sym) ELSE DevCPM.err(s) END
332 END CheckSym;
334 BEGIN
335 IF debugImport THEN Log.String("module " + m.name); Log.Ln END;
336 DevCPS.Init; DevCPS.Get(sym);
337 IF sym = module THEN DevCPS.Get(sym) ELSE err(16) END;
338 IF sym = ident THEN
339 SelfName := DevCPS.name$; DevCPS.Get(sym);
340 IF sym = lbrak THEN
341 INCL(DevCPM.options, DevCPM.interface); DevCPS.Get(sym);
342 IF sym = eql THEN DevCPS.Get(sym)
343 ELSE INCL(DevCPM.options, DevCPM.noCode)
344 END;
345 IF sym = string THEN INCL(m.flags, library); m.library := DevCPS.str$; DevCPS.Get(sym)
346 ELSE err(string)
347 END;
348 CheckSym(rbrak)
349 END;
350 CheckSym(semicolon);
351 IF sym = import THEN DevCPS.Get(sym);
352 LOOP
353 IF sym = ident THEN
354 aliasName := DevCPS.name$; impName := aliasName$; DevCPS.Get(sym);
355 IF sym = becomes THEN DevCPS.Get(sym);
356 IF sym = ident THEN impName := DevCPS.name$; DevCPS.Get(sym) ELSE err(ident) END
357 END;
358 Import(m, impName)
359 ELSE err(ident)
360 END;
361 IF sym = comma THEN DevCPS.Get(sym)
362 ELSIF sym = ident THEN err(comma)
363 ELSE EXIT
364 END
365 END;
366 CheckSym(semicolon)
367 END;
368 LOOP (* preprocessor must read module fully *)
369 IF sym = end THEN
370 DevCPS.Get(sym);
371 IF sym = ident THEN
372 DevCPS.Get(sym);
373 IF sym = period THEN
374 IF DevCPS.name # SelfName THEN err(4) END;
375 EXIT
376 ELSIF sym = eof THEN
377 err(period);
378 EXIT
379 END
380 ELSIF sym = eof THEN
381 err(ident);
382 EXIT
383 END;
384 ELSIF sym = eof THEN
385 err(end);
386 EXIT
387 ELSE
388 DevCPS.Get(sym);
389 END
390 END
391 ELSE err(ident)
392 END;
393 DevCPS.str := NIL
394 END ParseModule;
396 PROCEDURE CheckModule (m: Module; source: String; OUT ok: BOOLEAN);
397 VAR s: Selector;
398 BEGIN
399 DevCPM.Init(source);
400 DevCPM.symList := m.dir;
401 (*DevCPM.codePath := m.outcode;*)
402 (*DevCPM.symPath := m.outsym;*)
403 DevCPM.name := m.name$;
404 INCL(DevCPM.options, DevCPM.comAware);
405 IF trap THEN
406 INCL(DevCPM.options, DevCPM.trap)
407 END;
408 (*IF oberon IN m.opts THEN INCL(DevCPM.options, DevCPM.oberon) END;*)
409 DevCPR.Init;
410 s := def.next;
411 WHILE s # NIL DO
412 DevCPR.Set(s.name, s.value);
413 s := s.next
414 END;
415 ParseModule(m);
416 DevCPR.Check;
417 ok := DevCPM.noerr;
418 IF DevCPR.used THEN INCL(m.flags, force) END;
419 DevCPR.Close;
420 DevCPM.InsertMarks;
421 DevCPM.Close;
422 Kernel.FastCollect
423 END CheckModule;
425 PROCEDURE MakePath (IN dir, name: Files.Name; IN type: Files.Type; OUT path: Files.Name);
426 BEGIN
427 ASSERT(name # "", 21);
428 IF dir = "" THEN path := modDir + "/" + name
429 ELSE path := dir + "/" + modDir + "/" + name
430 END;
431 Kernel.MakeFileName(path, type)
432 END MakePath;
434 PROCEDURE Open (loc: Files.Locator; IN sub, name: Files.Name; OUT path: Files.Name; OUT text: DswDocuments.Model);
435 VAR res: INTEGER;
436 BEGIN
437 ASSERT(loc # NIL, 20);
438 ASSERT(name # "", 21);
439 (* !!! use Kernel.MakeFileName instead ".ext" concat !!! *)
440 MakePath(sub, name, "cp", path);
441 DswDocuments.Open(loc, name + ".cp", text, res);
442 IF text = NIL THEN
443 MakePath(sub, name, "odc", path);
444 DswDocuments.Open(loc, name + ".odc", text, res);
445 IF (text = NIL) & (sub = "") THEN
446 MakePath(sysDir, name, "cp", path);
447 loc := Files.dir.This(sysDir).This(modDir);
448 DswDocuments.Open(loc, name + ".cp", text, res);
449 IF text = NIL THEN
450 MakePath(sysDir, name, "odc", path);
451 DswDocuments.Open(loc, name + ".odc", text, res);
452 IF text = NIL THEN
453 path := ""
454 END
455 END
456 END
457 END
458 END Open;
460 PROCEDURE GetSource (IN modName: ARRAY OF CHAR; list: DevCPM.Directory; OUT path: Files.Name; OUT s: String);
461 VAR
462 sub, name: Files.Name; loc: Files.Locator; base: DevCPM.Directory;
463 text: DswDocuments.Model; r: DswDocuments.Reader; i, res: INTEGER;
464 BEGIN
465 s := NIL; path := ""; base := list;
466 Kernel.SplitName(modName, sub, name);
467 loc := Files.dir.This(sub).This(modDir);
468 Open(loc, sub, name, path, text);
469 WHILE (text = NIL) & (base # NIL) DO
470 ASSERT(base.legacy, 100);
471 loc := Files.dir.This(base.path).This(sub).This(modDir);
472 Open(loc, sub, name, path, text);
473 base := base.next
474 END;
475 IF text # NIL THEN
476 NEW(s, text.Length() + 1);
477 IF s # NIL THEN
478 r := text.NewReader(NIL);
479 FOR i := 0 TO text.Length() - 1 DO
480 r.Read; s[i] := r.char
481 END
482 END
483 END
484 END GetSource;
486 PROCEDURE Trace (m, parent: Module; VAR lno: INTEGER);
487 VAR i: INTEGER;
488 BEGIN
489 IF ~(trace IN m.flags) THEN
490 INCL(m.flags, trace);
491 FOR i := 0 TO m.mno - 1 DO
492 Trace(m.imp[i], m, lno);
493 m.depth := MAX(m.depth, m.imp[i].depth + 1)
494 END;
495 IF ~(imported IN m.flags) THEN
496 INCL(m.flags, imported);
497 lnkList[lno] := m;
498 INC(lno)
499 END;
500 EXCL(m.flags, trace)
501 ELSE
502 Error("recursive import of ^0 in ^1", m.name$, parent.name$, 0)
503 END
504 END Trace;
506 PROCEDURE Sort;
507 VAR i, j: INTEGER; m: Module;
508 BEGIN
509 ASSERT((mno = 0) OR (lnkList[0] # NIL), 20);
510 cmpList := lnkList;
511 i := 1;
512 WHILE i < mno DO
513 m := cmpList[i];
514 j := i - 1;
515 WHILE (j >= 0) & (cmpList[j].depth > m.depth) DO
516 cmpList[j + 1] := cmpList[j];
517 DEC(j)
518 END;
519 cmpList[j + 1] := m;
520 INC(i)
521 END
522 END Sort;
524 PROCEDURE CheckDeps;
525 VAR i, j, num: INTEGER; m: Module; src: String; ok: BOOLEAN;
526 BEGIN
527 i := 0; rno := mno;
528 WHILE (err = 0) & (i < mno) DO
529 m := modList[i];
530 GetSource(m.name$, m.dir, m.odc, src);
531 IF src # NIL THEN
532 CheckModule(m, src, ok);
533 IF ~ok THEN INC(err) END
534 ELSE
535 Error("unable to open module ^1", m.name$, "", 0)
536 END;
537 INC(i)
538 END;
539 INC(err, werr);
540 num := 0;
541 FOR i := 0 TO rno - 1 DO
542 Trace(modList[i], modList[i], num)
543 END;
544 ASSERT((err # 0) OR (num = mno), 100);
545 Sort;
546 IF debugOrder THEN
547 Log.String("Parallel depth:"); Log.Ln;
548 FOR i := 0 TO mno - 1 DO
549 Log.String(" " + cmpList[i].name); Log.Int(cmpList[i].depth); Log.Ln;
550 END
551 END
552 END CheckDeps;
554 PROCEDURE IsCompiled (m: Module): BOOLEAN;
555 CONST target = {hasSym, hasObj};
556 VAR i: INTEGER; ready: BOOLEAN;
557 BEGIN
558 ASSERT(m # NIL, 20);
559 i := 0;
560 ready := ~(hasErrors IN m.flags) & (m.flags * target = target);
561 WHILE ready & (i < m.mno) DO
562 ready := IsCompiled(m.imp[i]);
563 INC(i)
564 END;
565 RETURN ready
566 END IsCompiled;
568 PROCEDURE Ready (m: Module): BOOLEAN;
569 CONST target = {hasSym, hasObj};
570 VAR i: INTEGER; ready: BOOLEAN;
571 BEGIN
572 i := 0;
573 ready := ~(hasErrors IN m.flags) & (m.flags * target # target) & (m.worker = NIL);
574 WHILE ready & (i < m.mno) DO
575 ready := IsCompiled(m.imp[i]);
576 INC(i)
577 END;
578 RETURN ready
579 END Ready;
581 PROCEDURE PrepareCompilerDeps (m: Module; p: DswProcs.Process; root, libsOnly: BOOLEAN);
582 VAR i: INTEGER; s: ARRAY 3 OF CHAR; lib: Library;
583 BEGIN
584 IF ~(trace IN m.flags) THEN
585 INCL(m.flags, trace);
586 FOR i := 0 TO m.mno - 1 DO
587 PrepareCompilerDeps(m.imp[i], p, FALSE, libsOnly)
588 END;
589 IF ~libsOnly OR (library IN m.flags) THEN
590 IF library IN m.flags THEN s := "-l" ELSE s := "-m" END;
591 IF root THEN s[1] := CAP(s[1]) END;
592 IF library IN m.flags THEN
593 lib := FindLib(m.library$);
594 IF lib # NIL THEN
595 IF lib.library$ # "" THEN
596 p.PutParam(s);
597 p.PutParam(lib.library$)
598 END
599 ELSE
600 p.PutParam(s);
601 p.PutParam(m.library$)
602 END
603 ELSE
604 p.PutParam(s);
605 p.PutParam(m.name$)
606 END
607 END;
608 EXCL(m.flags, trace)
609 END
610 END PrepareCompilerDeps;
612 PROCEDURE PrepareCompiler (m: Module): DswProcs.Process;
613 VAR p: DswProcs.Process; s: Selector; i: INTEGER;
614 BEGIN
615 ASSERT(m # NIL, 20);
616 ASSERT(m.odc # "", 21);
617 ASSERT(m.worker = NIL, 22);
618 p := DswProcs.dir.New();
619 p.Program(base + "/" + target + "/" + "build");
620 p.PutParam(m.odc);
621 IF nocode1 THEN p.PutParam("-b") END;
622 IF nocode2 THEN p.PutParam("-x") END;
623 IF force IN m.flags THEN p.PutParam("-f") END;
624 IF symonly OR (library IN m.flags) THEN p.PutParam("-s") END;
625 s := def.next;
626 WHILE s # NIL DO
627 IF s.value THEN p.PutParam("-D") ELSE p.PutParam("-d") END;
628 p.PutParam(s.name$);
629 s := s.next
630 END;
631 FOR i := 0 TO m.mno - 1 DO
632 PrepareCompilerDeps(m.imp[i], p, TRUE, FALSE);
633 END;
634 RETURN p
635 END PrepareCompiler;
637 PROCEDURE Compile;
638 VAR i, j, num, res: INTEGER; ok: BOOLEAN; m: Module; w: DswProcs.Process;
639 BEGIN
640 IF mno = 0 THEN RETURN END;
641 num := 0; j := 0;
642 WHILE (err = 0) & (num < mno) OR (j > 0) DO
643 i := 0;
644 WHILE (err = 0) & (i < mno) & (j < jobs) DO
645 m := cmpList[i];
646 IF Ready(m) THEN
647 w := PrepareCompiler(m);
648 IF debugJobs THEN Log.String("Start job " + m.name) END;
649 w.Execute(ok);
650 IF ok THEN
651 IF debugJobs THEN Log.String(" ok") END;
652 m.worker := w;
653 INC(j)
654 ELSE
655 IF debugJobs THEN Log.String(" fail") END;
656 INCL(m.flags, hasErrors);
657 INC(err)
658 END;
659 IF debugJobs THEN Log.Ln END
660 END;
661 INC(i)
662 END;
663 WHILE (err = 0) & (j >= jobs) OR (j > 0) DO
664 i := 0;
665 WHILE (j > 0) & (i < mno) DO
666 m := cmpList[i];
667 w := m.worker;
668 IF (w # NIL) & w.IsTerminated() THEN
669 res := w.Result();
670 IF debugJobs THEN Log.String("Stop job " + m.name); Log.Int(res); Log.Ln END;
671 IF res = 0 THEN
672 INCL(m.flags, hasObj);
673 INCL(m.flags, hasSym);
674 INC(num)
675 ELSE
676 INCL(m.flags, hasErrors);
677 INC(err)
678 END;
679 m.worker := NIL;
680 DEC(j)
681 END;
682 INC(i)
683 END
684 END
685 END
686 END Compile;
688 PROCEDURE Link;
689 VAR p: DswProcs.Process; ok: BOOLEAN; i, res: INTEGER;
690 BEGIN
691 IF ~symonly & (exe # NIL) THEN
692 p := DswProcs.dir.New();
693 p.Program(base + "/" + target + "/" + "link");
694 p.PutParam(exe$);
695 FOR i := 0 TO mno - 1 DO
696 IF ~(library IN lnkList[i].flags) THEN
697 p.PutParam(lnkList[i].name$)
698 END
699 END;
700 FOR i := 0 TO mno - 1 DO
701 IF library IN lnkList[i].flags THEN
702 PrepareCompilerDeps(lnkList[i], p, FALSE, TRUE)
703 END
704 END;
705 p.Execute(ok);
706 IF ok THEN
707 p.Wait;
708 res := p.Result();
709 IF res # 0 THEN
710 Error("link failed with code ^2", "", "", res)
711 END
712 ELSE Error("link failed: unable to execute script", "", "", 0)
713 END
714 END
715 END Link;
717 PROCEDURE Cleanup;
718 VAR p: DswProcs.Process; ok: BOOLEAN; res: INTEGER;
719 BEGIN
720 IF clean THEN
721 p := DswProcs.dir.New();
722 p.Program(base + "/" + target + "/" + "clean");
723 p.Execute(ok);
724 IF ok THEN
725 p.Wait;
726 res := p.Result();
727 IF res # 0 THEN
728 Error("cleanup failed with code ^2", "", "", res)
729 END
730 ELSE Error("cleanup failed: unable to execute script", "", "", 0)
731 END
732 END
733 END Cleanup;
735 PROCEDURE Main;
736 BEGIN
737 IF Kernel.trapCount = 0 THEN
738 ParseArgs;
739 IF err = 0 THEN
740 CheckParams;
741 IF err = 0 THEN
742 CheckDeps;
743 IF err = 0 THEN
744 Cleanup;
745 IF err = 0 THEN
746 Compile;
747 IF err = 0 THEN
748 Link
749 END
750 END
751 END
752 END
753 END
754 ELSE Error("trap occured", "", "", 0)
755 END;
756 IF err = 0 THEN Kernel.Quit(0)
757 ELSE Kernel.Quit(1)
758 END
759 END Main;
761 BEGIN
762 NEW(def);
763 ASSERT(def # NIL, 100);
764 Kernel.intTrap := FALSE;
765 Kernel.Start(Main)
766 END DswMakeMain.