DEADSOFTWARE

cpmake: fix open source out of any subsystem
[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 DefineNew (IN n: ARRAY OF CHAR);
127 BEGIN
128 Define(n, FALSE);
129 END DefineNew;
131 PROCEDURE AddModule (IN n: ARRAY OF CHAR; selectors: Selector; dir: DevCPM.Directory);
132 VAR i, res: INTEGER; m: Module;
133 BEGIN
134 i := IdentLen(n);
135 IF (i # 0) & (n[i] = 0X) THEN
136 i := 0;
137 WHILE (i < mno) & (modList[i].name$ # n$) DO INC(i) END;
138 IF i >= mno THEN
139 NEW(m);
140 Strings.StringToUtf8(n, m.name, res);
141 ASSERT(res = 0);
142 m.dir := dir;
143 modList[i] := m;
144 INC(mno)
145 END
146 ELSE
147 Error("invalid module name", "", "", 0)
148 END
149 END AddModule;
151 PROCEDURE AddLibrary (IN key, val: ARRAY OF CHAR);
152 VAR x: Library;
153 BEGIN
154 x := libList;
155 WHILE (x # NIL) & (x.name$ # key$) DO x := x.next END;
156 IF x # NIL THEN x.library := val$
157 ELSE NEW(x); x.name := key$; x.library := val$; x.next := libList; libList := x
158 END
159 END AddLibrary;
161 PROCEDURE AddLib (IN s: ARRAY OF CHAR);
162 VAR key, val: Name; i, j: INTEGER;
163 BEGIN
164 i := 0; j := 0;
165 WHILE (s[i] # 0X) & (s[i] # "=") DO
166 key[j] := s[i];
167 INC(j);
168 INC(i)
169 END;
170 key[j] := 0X;
171 j := 0;
172 IF s[i] = "=" THEN
173 INC(i);
174 WHILE s[i] # 0X DO
175 val[j] := s[i];
176 INC(j);
177 INC(i)
178 END
179 END;
180 val[j] := 0X;
181 IF key # "" THEN AddLibrary(key, val)
182 ELSE Error("empty library key", "", "", 0)
183 END
184 END AddLib;
186 PROCEDURE FindLib (IN key: ARRAY OF CHAR): Library;
187 VAR x: Library;
188 BEGIN
189 x := libList;
190 WHILE (x # NIL) & (x.name$ # key$) DO x := x.next END;
191 RETURN x
192 END FindLib;
194 PROCEDURE StrToInt (IN s: ARRAY OF CHAR; def: INTEGER): INTEGER;
195 VAR x, res: INTEGER;
196 BEGIN
197 Strings.StringToInt(s, x, res);
198 IF res # 0 THEN
199 Error("invalid integer value", s, "", 0);
200 x := def
201 END;
202 RETURN x
203 END StrToInt;
205 PROCEDURE NewStr (IN s: ARRAY OF CHAR): String;
206 VAR p: String;
207 BEGIN
208 NEW(p, LEN(s$) + 1); p^ := s$;
209 RETURN p
210 END NewStr;
212 PROCEDURE Help;
213 BEGIN
214 Log.String("Usage: cpmake [options] module..."); Log.Ln;
215 Log.String("Options:"); Log.Ln;
216 Log.String(" -a Enable automatic dependency resolution"); Log.Ln;
217 Log.String(" -b Do not compile modules"); Log.Ln;
218 Log.String(" -x Do not link objects"); Log.Ln;
219 Log.String(" -c Remove all generated files"); Log.Ln;
220 Log.String(" -s Generate symbol files only"); Log.Ln;
221 Log.String(" -d selector Add selector"); Log.Ln;
222 Log.String(" -r lib[=s] Replace library name on link stage"); Log.Ln;
223 Log.String(" -t target Specify target rules"); Log.Ln;
224 Log.String(" -o file Generate object file"); Log.Ln;
225 Log.String(" -j num Specifies the number of jobs to run simultaneously"); Log.Ln;
226 Log.String(" -f path Specifies path to directory with targets"); Log.Ln;
227 Log.String(" -h Print help"); Log.Ln;
228 Log.String(" -v Print version"); Log.Ln;
229 Kernel.Quit(0)
230 END Help;
232 PROCEDURE ParseArgs;
233 BEGIN
234 exe := NIL; auto := FALSE; jobs := 1; def.next := NIL; mno := 0; rno := 0;
235 target := NewStr("default"); base := NewStr("cprules");
236 LOOP
237 CASE DswOpts.GetOpt("acbxd:sgGo:t:j:f:r:h") OF
238 | "a": auto := TRUE
239 | "b": nocode1 := TRUE
240 | "x": nocode2 := TRUE
241 | "c": clean := TRUE
242 | "g": trap := TRUE
243 | "G": Kernel.intTrap := TRUE
244 | "s": symonly := TRUE
245 | "f": base := DswOpts.str
246 | "d": Define(DswOpts.str, TRUE)
247 | "r": AddLib(DswOpts.str)
248 | "h": Help
249 | "j": jobs := MIN(MAX(StrToInt(DswOpts.str, 1), 1), maxJobs)
250 | "o": exe := DswOpts.str
251 | "t": target := DswOpts.str
252 | "v": Log.String(version); Log.Ln; Kernel.Quit(0)
253 | ":": Error("missing argument for option -^0", DswOpts.str, "", 0)
254 | "?": Error("unknown option -^0", DswOpts.str, "", 0)
255 | "$": AddModule(DswOpts.str, def, dirList)
256 | 00X: EXIT
257 END
258 END
259 END ParseArgs;
261 PROCEDURE ReadLines (loc: Files.Locator; IN name: Files.Name; p: PROCEDURE (IN s: ARRAY OF CHAR));
262 VAR s: Name; m: DswDocuments.Model; r: DswDocuments.Reader; i, res: INTEGER;
263 BEGIN
264 ASSERT(loc # NIL, 20);
265 ASSERT(name # "", 21);
266 ASSERT(p # NIL, 22);
267 DswDocuments.Open(loc, name, m, res);
268 IF res = 0 THEN
269 r := m.NewReader(NIL);
270 r.SetPos(0);
271 r.Read;
272 WHILE ~r.eot DO
273 i := 0;
274 WHILE ~r.eot & (r.char <= 20X) DO r.Read END;
275 WHILE ~r.eot & (r.char > 20X) DO s[i] := r.char; r.Read; INC(i) END;
276 IF i # 0 THEN s[i] := 0X; p(s) END
277 END
278 END
279 END ReadLines;
281 PROCEDURE CheckParams;
282 VAR loc: Files.Locator;
283 BEGIN
284 IF (exe # NIL) & (exe^ = "") THEN
285 Error("specified empty file name for exe", "", "", 0)
286 END;
287 IF target^ = "" THEN
288 Error("specified empty rule", "", "", 0)
289 END;
290 IF base^ = "" THEN
291 Error("specified empty path to cpmake rules", "", "", 0)
292 END;
293 loc := Files.dir.This(base).This(target);
294 ReadLines(loc, "defines", DefineNew);
295 ReadLines(loc, "libs", AddLib)
296 END CheckParams;
298 (* --------- loader --------- *)
300 PROCEDURE Import (m: Module; IN name: DevCPT.Name);
301 VAR i, j: INTEGER; imp: Module;
302 BEGIN
303 ASSERT(m # NIL, 20);
304 ASSERT(name # "", 21);
305 IF debugImport THEN Log.String(" import "); Log.String(name$) END;
306 IF name = "SYSTEM" THEN INCL(DevCPM.options, DevCPM.sysImp)
307 ELSIF name = "COM" THEN INCL(DevCPM.options, DevCPM.com)
308 ELSIF name = "JAVA" THEN INCL(DevCPM.options, DevCPM.java)
309 ELSE
310 IF debugImport THEN Log.Char(" ") END;
311 i := 0; (* find module in local list *)
312 WHILE (i < m.mno) & (m.imp[i].name$ # name$) DO INC(i) END;
313 IF i >= m.mno THEN
314 j := 0; (* find module in global list *)
315 WHILE (j < mno) & (modList[j].name$ # name$) DO INC(j) END;
316 IF j >= mno THEN
317 IF ~auto THEN
318 Log.String("module " + name + " required before " + m.name); Log.Ln; INC(werr)
319 END;
320 NEW(imp); imp.name := name$;
321 modList[mno] := imp; INC(mno)
322 ELSE
323 imp := modList[j]
324 END;
325 m.imp[m.mno] := imp; INC(m.mno)
326 ELSE DevCPM.err(1)
327 END
328 END;
329 IF debugImport THEN Log.Ln END;
330 END Import;
332 PROCEDURE ParseModule (m: Module);
333 VAR sym: BYTE; SelfName, impName, aliasName: DevCPT.Name;
335 PROCEDURE err (n: SHORTINT);
336 BEGIN DevCPM.err(n)
337 END err;
339 PROCEDURE CheckSym(s: SHORTINT);
340 BEGIN
341 IF sym = s THEN DevCPS.Get(sym) ELSE DevCPM.err(s) END
342 END CheckSym;
344 BEGIN
345 IF debugImport THEN Log.String("module " + m.name); Log.Ln END;
346 DevCPS.Init; DevCPS.Get(sym);
347 IF sym = module THEN DevCPS.Get(sym) ELSE err(16) END;
348 IF sym = ident THEN
349 SelfName := DevCPS.name$; DevCPS.Get(sym);
350 IF sym = lbrak THEN
351 INCL(DevCPM.options, DevCPM.interface); DevCPS.Get(sym);
352 IF sym = eql THEN DevCPS.Get(sym)
353 ELSE INCL(DevCPM.options, DevCPM.noCode)
354 END;
355 IF sym = string THEN INCL(m.flags, library); m.library := DevCPS.str$; DevCPS.Get(sym)
356 ELSE err(string)
357 END;
358 CheckSym(rbrak)
359 END;
360 CheckSym(semicolon);
361 IF sym = import THEN DevCPS.Get(sym);
362 LOOP
363 IF sym = ident THEN
364 aliasName := DevCPS.name$; impName := aliasName$; DevCPS.Get(sym);
365 IF sym = becomes THEN DevCPS.Get(sym);
366 IF sym = ident THEN impName := DevCPS.name$; DevCPS.Get(sym) ELSE err(ident) END
367 END;
368 Import(m, impName)
369 ELSE err(ident)
370 END;
371 IF sym = comma THEN DevCPS.Get(sym)
372 ELSIF sym = ident THEN err(comma)
373 ELSE EXIT
374 END
375 END;
376 CheckSym(semicolon)
377 END;
378 LOOP (* preprocessor must read module fully *)
379 IF sym = end THEN
380 DevCPS.Get(sym);
381 IF sym = ident THEN
382 DevCPS.Get(sym);
383 IF sym = period THEN
384 IF DevCPS.name # SelfName THEN err(4) END;
385 EXIT
386 ELSIF sym = eof THEN
387 err(period);
388 EXIT
389 END
390 ELSIF sym = eof THEN
391 err(ident);
392 EXIT
393 END;
394 ELSIF sym = eof THEN
395 err(end);
396 EXIT
397 ELSE
398 DevCPS.Get(sym);
399 END
400 END
401 ELSE err(ident)
402 END;
403 DevCPS.str := NIL
404 END ParseModule;
406 PROCEDURE CheckModule (m: Module; source: String; OUT ok: BOOLEAN);
407 VAR s: Selector;
408 BEGIN
409 DevCPM.Init(source);
410 DevCPM.symList := m.dir;
411 (*DevCPM.codePath := m.outcode;*)
412 (*DevCPM.symPath := m.outsym;*)
413 DevCPM.name := m.name$;
414 INCL(DevCPM.options, DevCPM.comAware);
415 IF trap THEN
416 INCL(DevCPM.options, DevCPM.trap)
417 END;
418 (*IF oberon IN m.opts THEN INCL(DevCPM.options, DevCPM.oberon) END;*)
419 DevCPR.Init;
420 s := def.next;
421 WHILE s # NIL DO
422 DevCPR.Set(s.name, s.value);
423 s := s.next
424 END;
425 ParseModule(m);
426 DevCPR.Check;
427 ok := DevCPM.noerr;
428 IF DevCPR.used THEN INCL(m.flags, force) END;
429 DevCPR.Close;
430 DevCPM.InsertMarks;
431 DevCPM.Close;
432 Kernel.FastCollect
433 END CheckModule;
435 PROCEDURE GetModText (IN base, sub, name: Files.Name; OUT path: Files.Name; OUT text: DswDocuments.Model);
436 VAR res: INTEGER; loc: Files.Locator;
437 BEGIN
438 ASSERT(name # "", 21);
439 IF sub = "" THEN
440 loc := Files.dir.This(base);
441 IF base = "" THEN path := name
442 ELSE path := base + "/" + name
443 END
444 ELSE
445 loc := Files.dir.This(base).This(sub).This(modDir);
446 IF base = "" THEN path := sub + "/" + modDir + "/" + name
447 ELSE path := base + "/" + sub + "/" + modDir + "/" + name
448 END
449 END;
450 DswDocuments.Open(loc, name, text, res)
451 END GetModText;
453 PROCEDURE Open (IN base, sub, name: Files.Name; OUT path: Files.Name; OUT text: DswDocuments.Model);
454 VAR cp, odc: Files.Name;
455 BEGIN
456 ASSERT(name # "", 20);
457 Files.dir.GetFileName(name, "cp", cp); (* !!! *)
458 GetModText(base, sub, cp, path, text);
459 IF text = NIL THEN
460 Files.dir.GetFileName(name, "odc", odc); (* !!! *)
461 GetModText(base, sub, odc, path, text);
462 IF (text = NIL) & (sub = "") THEN
463 GetModText(base, sysDir, cp, path, text);
464 IF text = NIL THEN
465 GetModText(base, sysDir, odc, path, text);
466 IF text = NIL THEN
467 path := ""
468 END
469 END
470 END
471 END
472 END Open;
474 PROCEDURE GetSource (IN modName: ARRAY OF CHAR; list: DevCPM.Directory; OUT path: Files.Name; OUT s: String);
475 VAR
476 sub, name: Files.Name;
477 base: DevCPM.Directory;
478 text: DswDocuments.Model;
479 r: DswDocuments.Reader;
480 i, res: INTEGER;
481 BEGIN
482 s := NIL; path := ""; base := list;
483 Kernel.SplitName(modName, sub, name);
484 Open("", sub, name, path, text);
485 WHILE (text = NIL) & (base # NIL) DO
486 ASSERT(base.legacy, 100);
487 Open(base.path, sub, name, path, text);
488 base := base.next
489 END;
490 IF text # NIL THEN
491 NEW(s, text.Length() + 1);
492 IF s # NIL THEN
493 r := text.NewReader(NIL);
494 FOR i := 0 TO text.Length() - 1 DO
495 r.Read; s[i] := r.char
496 END
497 END
498 END
499 END GetSource;
501 PROCEDURE Trace (m, parent: Module; VAR lno: INTEGER);
502 VAR i: INTEGER;
503 BEGIN
504 IF ~(trace IN m.flags) THEN
505 INCL(m.flags, trace);
506 FOR i := 0 TO m.mno - 1 DO
507 Trace(m.imp[i], m, lno);
508 m.depth := MAX(m.depth, m.imp[i].depth + 1)
509 END;
510 IF ~(imported IN m.flags) THEN
511 INCL(m.flags, imported);
512 lnkList[lno] := m;
513 INC(lno)
514 END;
515 EXCL(m.flags, trace)
516 ELSE
517 Error("recursive import of ^0 in ^1", m.name$, parent.name$, 0)
518 END
519 END Trace;
521 PROCEDURE Sort;
522 VAR i, j: INTEGER; m: Module;
523 BEGIN
524 ASSERT((mno = 0) OR (lnkList[0] # NIL), 20);
525 cmpList := lnkList;
526 i := 1;
527 WHILE i < mno DO
528 m := cmpList[i];
529 j := i - 1;
530 WHILE (j >= 0) & (cmpList[j].depth > m.depth) DO
531 cmpList[j + 1] := cmpList[j];
532 DEC(j)
533 END;
534 cmpList[j + 1] := m;
535 INC(i)
536 END
537 END Sort;
539 PROCEDURE CheckDeps;
540 VAR i, j, num: INTEGER; m: Module; src: String; ok: BOOLEAN;
541 BEGIN
542 i := 0; rno := mno;
543 WHILE (err = 0) & (i < mno) DO
544 m := modList[i];
545 GetSource(m.name$, m.dir, m.odc, src);
546 IF src # NIL THEN
547 CheckModule(m, src, ok);
548 IF ~ok THEN INC(err) END
549 ELSE
550 Error("unable to open module ^0", m.name$, "", 0)
551 END;
552 INC(i)
553 END;
554 INC(err, werr);
555 num := 0;
556 FOR i := 0 TO rno - 1 DO
557 Trace(modList[i], modList[i], num)
558 END;
559 ASSERT((err # 0) OR (num = mno), 100);
560 Sort;
561 IF debugOrder THEN
562 Log.String("Parallel depth:"); Log.Ln;
563 FOR i := 0 TO mno - 1 DO
564 Log.String(" " + cmpList[i].name); Log.Int(cmpList[i].depth); Log.Ln;
565 END
566 END
567 END CheckDeps;
569 PROCEDURE IsCompiled (m: Module): BOOLEAN;
570 CONST target = {hasSym, hasObj};
571 VAR i: INTEGER; ready: BOOLEAN;
572 BEGIN
573 ASSERT(m # NIL, 20);
574 i := 0;
575 ready := ~(hasErrors IN m.flags) & (m.flags * target = target);
576 WHILE ready & (i < m.mno) DO
577 ready := IsCompiled(m.imp[i]);
578 INC(i)
579 END;
580 RETURN ready
581 END IsCompiled;
583 PROCEDURE Ready (m: Module): BOOLEAN;
584 CONST target = {hasSym, hasObj};
585 VAR i: INTEGER; ready: BOOLEAN;
586 BEGIN
587 i := 0;
588 ready := ~(hasErrors IN m.flags) & (m.flags * target # target) & (m.worker = NIL);
589 WHILE ready & (i < m.mno) DO
590 ready := IsCompiled(m.imp[i]);
591 INC(i)
592 END;
593 RETURN ready
594 END Ready;
596 PROCEDURE PrepareCompilerDeps (m: Module; p: DswProcs.Process; root, libsOnly: BOOLEAN);
597 VAR i: INTEGER; s: ARRAY 3 OF CHAR; lib: Library;
598 BEGIN
599 IF ~(trace IN m.flags) THEN
600 INCL(m.flags, trace);
601 FOR i := 0 TO m.mno - 1 DO
602 PrepareCompilerDeps(m.imp[i], p, FALSE, libsOnly)
603 END;
604 IF ~libsOnly OR (library IN m.flags) THEN
605 IF library IN m.flags THEN s := "-l" ELSE s := "-m" END;
606 IF root THEN s[1] := CAP(s[1]) END;
607 IF library IN m.flags THEN
608 lib := FindLib(m.library$);
609 IF lib # NIL THEN
610 IF lib.library$ # "" THEN
611 p.PutParam(s);
612 p.PutParam(lib.library$)
613 END
614 ELSE
615 p.PutParam(s);
616 p.PutParam(m.library$)
617 END
618 ELSE
619 p.PutParam(s);
620 p.PutParam(m.name$)
621 END
622 END;
623 EXCL(m.flags, trace)
624 END
625 END PrepareCompilerDeps;
627 PROCEDURE PrepareCompiler (m: Module): DswProcs.Process;
628 VAR p: DswProcs.Process; s: Selector; i: INTEGER;
629 BEGIN
630 ASSERT(m # NIL, 20);
631 ASSERT(m.odc # "", 21);
632 ASSERT(m.worker = NIL, 22);
633 p := DswProcs.dir.New();
634 p.Program(base + "/" + target + "/" + "build");
635 p.PutParam(m.odc);
636 IF nocode1 THEN p.PutParam("-b") END;
637 IF nocode2 THEN p.PutParam("-x") END;
638 IF force IN m.flags THEN p.PutParam("-f") END;
639 IF symonly OR (library IN m.flags) THEN p.PutParam("-s") END;
640 s := def.next;
641 WHILE s # NIL DO
642 IF s.value THEN p.PutParam("-D") ELSE p.PutParam("-d") END;
643 p.PutParam(s.name$);
644 s := s.next
645 END;
646 FOR i := 0 TO m.mno - 1 DO
647 PrepareCompilerDeps(m.imp[i], p, TRUE, FALSE);
648 END;
649 RETURN p
650 END PrepareCompiler;
652 PROCEDURE Compile;
653 VAR i, j, num, res: INTEGER; ok: BOOLEAN; m: Module; w: DswProcs.Process;
654 BEGIN
655 IF mno = 0 THEN RETURN END;
656 num := 0; j := 0;
657 WHILE (err = 0) & (num < mno) OR (j > 0) DO
658 i := 0;
659 WHILE (err = 0) & (i < mno) & (j < jobs) DO
660 m := cmpList[i];
661 IF Ready(m) THEN
662 w := PrepareCompiler(m);
663 IF debugJobs THEN Log.String("Start job " + m.name) END;
664 w.Execute(ok);
665 IF ok THEN
666 IF debugJobs THEN Log.String(" ok") END;
667 m.worker := w;
668 INC(j)
669 ELSE
670 IF debugJobs THEN Log.String(" fail") END;
671 INCL(m.flags, hasErrors);
672 INC(err)
673 END;
674 IF debugJobs THEN Log.Ln END
675 END;
676 INC(i)
677 END;
678 WHILE (err = 0) & (j >= jobs) OR (j > 0) DO
679 i := 0;
680 WHILE (j > 0) & (i < mno) DO
681 m := cmpList[i];
682 w := m.worker;
683 IF (w # NIL) & w.IsTerminated() THEN
684 res := w.Result();
685 IF debugJobs THEN Log.String("Stop job " + m.name); Log.Int(res); Log.Ln END;
686 IF res = 0 THEN
687 INCL(m.flags, hasObj);
688 INCL(m.flags, hasSym);
689 INC(num)
690 ELSE
691 INCL(m.flags, hasErrors);
692 INC(err)
693 END;
694 m.worker := NIL;
695 DEC(j)
696 END;
697 INC(i)
698 END
699 END
700 END
701 END Compile;
703 PROCEDURE Link;
704 VAR p: DswProcs.Process; ok: BOOLEAN; i, res: INTEGER;
705 BEGIN
706 IF ~symonly & (exe # NIL) THEN
707 p := DswProcs.dir.New();
708 p.Program(base + "/" + target + "/" + "link");
709 p.PutParam(exe$);
710 FOR i := 0 TO mno - 1 DO
711 IF ~(library IN lnkList[i].flags) THEN
712 p.PutParam(lnkList[i].name$)
713 END
714 END;
715 FOR i := 0 TO mno - 1 DO
716 IF library IN lnkList[i].flags THEN
717 PrepareCompilerDeps(lnkList[i], p, FALSE, TRUE)
718 END
719 END;
720 p.Execute(ok);
721 IF ok THEN
722 p.Wait;
723 res := p.Result();
724 IF res # 0 THEN
725 Error("link failed with code ^2", "", "", res)
726 END
727 ELSE Error("link failed: unable to execute script", "", "", 0)
728 END
729 END
730 END Link;
732 PROCEDURE Cleanup;
733 VAR p: DswProcs.Process; ok: BOOLEAN; res: INTEGER;
734 BEGIN
735 IF clean THEN
736 p := DswProcs.dir.New();
737 p.Program(base + "/" + target + "/" + "clean");
738 p.Execute(ok);
739 IF ok THEN
740 p.Wait;
741 res := p.Result();
742 IF res # 0 THEN
743 Error("cleanup failed with code ^2", "", "", res)
744 END
745 ELSE Error("cleanup failed: unable to execute script", "", "", 0)
746 END
747 END
748 END Cleanup;
750 PROCEDURE Main;
751 BEGIN
752 IF Kernel.trapCount = 0 THEN
753 ParseArgs;
754 IF err = 0 THEN
755 CheckParams;
756 IF err = 0 THEN
757 CheckDeps;
758 IF err = 0 THEN
759 Cleanup;
760 IF err = 0 THEN
761 Compile;
762 IF err = 0 THEN
763 Link
764 END
765 END
766 END
767 END
768 END
769 ELSE Error("trap occured", "", "", 0)
770 END;
771 IF err = 0 THEN Kernel.Quit(0)
772 ELSE Kernel.Quit(1)
773 END
774 END Main;
776 BEGIN
777 NEW(def);
778 ASSERT(def # NIL, 100);
779 Kernel.intTrap := FALSE;
780 Kernel.Start(Main)
781 END DswMakeMain.