DEADSOFTWARE

57a46d910d2845167cb7a58a763c4b0f53b360ad
[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 maxImps = 127;
7 maxJobs = maxImps;
9 (* symbol values *)
10 null = 0; times = 1; slash = 2; div = 3; mod = 4;
11 and = 5; plus = 6; minus = 7; or = 8; eql = 9;
12 neq = 10; lss = 11; leq = 12; gtr = 13; geq = 14;
13 in = 15; is = 16; arrow = 17; dollar = 18; period = 19;
14 comma = 20; colon = 21; upto = 22; rparen = 23; rbrak = 24;
15 rbrace = 25; of = 26; then = 27; do = 28; to = 29;
16 by = 30; not = 33;
17 lparen = 40; lbrak = 41; lbrace = 42; becomes = 44;
18 number = 45; nil = 46; string = 47; ident = 48; semicolon = 49;
19 bar = 50; end = 51; else = 52; elsif = 53; until = 54;
20 if = 55; case = 56; while = 57; repeat = 58; for = 59;
21 loop = 60; with = 61; exit = 62; return = 63; array = 64;
22 record = 65; pointer = 66; begin = 67; const = 68; type = 69;
23 var = 70; out = 71; procedure = 72; close = 73; import = 74;
24 module = 75; eof = 76;
26 (* module state flags *)
27 imported = 0; trace = 1; hasObj = 2; hasSym = 3; hasErrors = 4; library = 5;
29 (* procesor types *)
30 anymach = 0; cmach = 1; mach386 = 10; mach68k = 20;
32 (* operation system types *)
33 anyos = 0; linux = 1; freebsd = 2; openbsd = 3; win32 = 4;
35 (* compiler types *)
36 anycp = 0; cpnative = 1; cpfront = 2;
38 (* internal linker types *)
39 anyint = 0; dev2 = 1;
41 debugImport = FALSE;
42 debugOrder = FALSE;
43 debugJobs = FALSE;
44 debugArgs = FALSE;
46 TYPE
47 String = POINTER TO ARRAY OF CHAR;
48 StringList = POINTER TO ARRAY OF String;
50 Selector = POINTER TO RECORD
51 name: DevCPT.Name;
52 value: BOOLEAN;
53 next: Selector
54 END;
56 Module = POINTER TO RECORD
57 name: DevCPT.Name;
58 path: Files.Name;
59 selectors: Selector; (* with head, list of selectors for this module *)
60 depth: INTEGER; (* 0: leaf, MAX: root *)
61 mno: INTEGER;
62 imp: ARRAY maxImps OF Module;
63 flags: SET;
64 worker: DswProcs.Process;
65 END;
67 VAR
68 err: INTEGER;
69 mno, rno: INTEGER; (* num modules *)
70 modList, lnkList, cmpList: ARRAY maxImps OF Module;
71 def: Selector; (* with head, global list of selectors *)
72 processor, compiler, os, linker: INTEGER;
73 cpcExe, cplExe: String;
74 cpcArgs, cplArgs: StringList;
75 auto: BOOLEAN;
76 jobs: INTEGER;
77 exe: String;
79 (* --------- options --------- *)
81 PROCEDURE IdentLen (IN s: ARRAY OF CHAR): INTEGER;
82 VAR i: INTEGER;
83 BEGIN
84 i := 0;
85 IF Strings.IsIdentStart(s[0]) THEN
86 REPEAT INC(i) UNTIL ~Strings.IsIdent(s[i])
87 END;
88 RETURN i
89 END IdentLen;
91 PROCEDURE Define (n: ARRAY OF CHAR);
92 VAR i: INTEGER; v: BOOLEAN; s: Selector;
93 BEGIN
94 i := IdentLen(n);
95 IF i # 0 THEN
96 IF ~((n[i] = 0X) OR (((n[i] = "+") OR (n[i] = "-")) & (n[i + 1] = 0X))) THEN
97 Log.String("option -D expect + or - after identifier"); Log.Ln; INC(err)
98 END;
99 v := n[i] # "-"; n[i] := 0X; s := def;
100 WHILE (s.next # NIL) & (s.next.name$ # n$) DO s := s.next END;
101 IF s.next = NIL THEN
102 NEW(s.next);
103 Strings.StringToUtf8(n, s.next.name, i);
104 ASSERT(i = 0)
105 END;
106 s.next.value := v
107 ELSE
108 Log.String("option -D expect identifier"); Log.Ln; INC(err)
109 END
110 END Define;
112 PROCEDURE Undefine (IN n: ARRAY OF CHAR);
113 VAR i: INTEGER; s: Selector;
114 BEGIN
115 i := IdentLen(n);
116 IF (i # 0) & (n[i] = 0X) THEN
117 s := def;
118 WHILE (s.next # NIL) & (s.next.name$ # n$) DO s := s.next END;
119 IF s.next # NIL THEN s.next := s.next.next END
120 ELSE
121 Log.String("option -U expect identifier"); Log.Ln; INC(err)
122 END
123 END Undefine;
125 PROCEDURE CopySelectorList (base: Selector): Selector;
126 VAR s, t, x: Selector;
127 BEGIN
128 ASSERT(base # NIL, 20);
129 s := base; NEW(t); x := t;
130 WHILE s # NIL DO
131 x^ := s^;
132 IF s.next # NIL THEN NEW(x.next); x := x.next END;
133 s := s.next
134 END;
135 RETURN t
136 END CopySelectorList;
138 PROCEDURE AddModule (IN n: ARRAY OF CHAR; selectors: Selector);
139 VAR i, res: INTEGER; m: Module;
140 BEGIN
141 i := IdentLen(n);
142 IF (i # 0) & (n[i] = 0X) THEN
143 i := 0;
144 WHILE (i < mno) & (modList[i].name$ # n$) DO INC(i) END;
145 IF i >= mno THEN
146 NEW(m);
147 Strings.StringToUtf8(n, m.name, res);
148 ASSERT(res = 0);
149 m.selectors := CopySelectorList(selectors);
150 modList[i] := m;
151 INC(mno)
152 END
153 ELSE
154 Log.String("module name must be identifier"); Log.Ln; INC(err)
155 END
156 END AddModule;
158 PROCEDURE StrToInt (IN s: ARRAY OF CHAR; def: INTEGER): INTEGER;
159 VAR x, res: INTEGER;
160 BEGIN
161 Strings.StringToInt(s, x, res);
162 IF res # 0 THEN
163 Log.String("expected integer"); Log.Ln; INC(err);
164 x := def
165 END;
166 RETURN x
167 END StrToInt;
169 PROCEDURE NewStr (IN s: ARRAY OF CHAR): String;
170 VAR p: String;
171 BEGIN
172 NEW(p, LEN(s$) + 1); p^ := s$;
173 RETURN p
174 END NewStr;
176 PROCEDURE ToStringList (IN s: ARRAY OF CHAR): StringList;
177 VAR i: INTEGER; ch, term: CHAR; pars: StringList;
179 PROCEDURE AddChar (c: CHAR);
180 VAR i, n, len: INTEGER; str: String;
181 BEGIN
182 IF pars = NIL THEN
183 NEW(pars, 1); NEW(pars[0], 2); pars[0, 0] := c
184 ELSE
185 n := LEN(pars) - 1;
186 len := LEN(pars[n]$);
187 NEW(str, len + 2);
188 FOR i := 0 TO len - 1 DO
189 str[i] := pars[n, i]
190 END;
191 str[i] := c;
192 pars[n] := str
193 END
194 END AddChar;
196 PROCEDURE AddLine;
197 VAR i, len: INTEGER; p: StringList;
198 BEGIN
199 IF pars = NIL THEN
200 NEW(pars, 1); i := 0;
201 ELSE
202 len := LEN(pars);
203 NEW(p, len + 1);
204 FOR i := 0 TO len - 1 DO
205 p[i] := pars[i]
206 END;
207 pars := p
208 END;
209 NEW(pars[i], 1)
210 END AddLine;
212 BEGIN
213 i := 0;
214 REPEAT ch := s[i]; INC(i) UNTIL ch # " ";
215 WHILE ch # 0X DO
216 CASE ch OF
217 | '"', "'":
218 term := ch; ch := s[i]; INC(i);
219 WHILE (ch # term) & (ch # 0X) DO
220 AddChar(ch); ch := s[i]; INC(i)
221 END;
222 IF ch # 0X THEN ch := s[i]; INC(i)
223 ELSE Log.String("unterminated string"); Log.Ln; INC(err)
224 END
225 | " ":
226 REPEAT ch := s[i]; INC(i) UNTIL ch # " ";
227 IF ch # 0X THEN AddLine END
228 ELSE
229 AddChar(ch); ch := s[i]; INC(i)
230 END
231 END;
232 RETURN pars
233 END ToStringList;
235 PROCEDURE Help;
236 BEGIN
237 Log.String("Usage: cpmake [options] module..."); Log.Ln;
238 Log.String("Options:"); Log.Ln;
239 Log.String(" -Tm cpu Generate code for specified processor"); Log.Ln;
240 Log.String(" none Unknown processor (cpfront only)"); Log.Ln;
241 Log.String(" 486 Intel 486"); Log.Ln;
242 Log.String(" -Ts os Generate code for specified operation system"); Log.Ln;
243 Log.String(" none Unknown operation system"); Log.Ln;
244 Log.String(" linux Linux"); Log.Ln;
245 Log.String(" -Tg compiler Specify Component Pascal compiler"); Log.Ln;
246 Log.String(" native BlackBox based native code compiler"); Log.Ln;
247 Log.String(" cpfront BlackBox based C code translator"); Log.Ln;
248 Log.String(" -Ti linker Specify internal linker (native only)"); Log.Ln;
249 Log.String(" dev2 Dev2 based ELF/PE linker"); Log.Ln;
250 (*
251 Log.String(" -Fp path Add path with project"); Log.Ln;
252 Log.String(" -Fx path Add postfix for project directories"); Log.Ln;
253 *)
254 Log.String(" -Xp path Use executable file for Component Pascal compiler"); Log.Ln;
255 Log.String(" -Xi path Use executable file for internal linker (native only)"); Log.Ln;
256 Log.String(" -Cg params Pass parameters to Component Pasacal compiler directly"); Log.Ln;
257 Log.String(" -Ci params Pass parameters to internal linker directly"); Log.Ln;
258 (*
259 Log.String(" -a Enable automatic dependency resolution"); Log.Ln;
260 *)
261 Log.String(" -o name Generate executable file"); Log.Ln;
262 Log.String(" -j num Specifies the number of jobs to run simultaneously"); Log.Ln;
263 Log.String(' -D ident["+"|"-"] Add preprocessor selector'); Log.Ln;
264 Log.String(' -U ident Remove preprocessor selector'); Log.Ln;
265 Log.String(" -h Print help"); Log.Ln;
266 Log.String(" -v Print version"); Log.Ln;
267 Kernel.Quit(1)
268 END Help;
270 PROCEDURE ParseTargetOpts;
271 VAR s: DswOpts.String;
272 BEGIN
273 CASE DswOpts.GetOpt("m:s:g:i:") OF
274 | "m":
275 s := DswOpts.str;
276 Strings.ToLower(s, s);
277 IF s$ = "none" THEN processor := anymach
278 ELSIF s$ = "486" THEN processor := mach386
279 ELSIF s$ = "68k" THEN processor := mach68k
280 ELSE Log.String("unknwon processor "); Log.String(s); Log.Ln; INC(err)
281 END
282 | "s":
283 s := DswOpts.str;
284 Strings.ToLower(s, s);
285 IF s$ = "none" THEN os := anyos
286 ELSIF s$ = "linux" THEN os := linux
287 ELSE Log.String("unknwon os "); Log.String(s); Log.Ln; INC(err)
288 END
289 | "g":
290 s := DswOpts.str;
291 Strings.ToLower(s, s);
292 IF s$ = "native" THEN compiler := cpnative
293 ELSIF s$ = "cpfront" THEN compiler := cpfront
294 ELSE Log.String("unknwon compiler "); Log.String(s); Log.Ln; INC(err)
295 END
296 | "i":
297 s := DswOpts.str;
298 Strings.ToLower(s, s);
299 IF s$ = "dev2" THEN linker := dev2
300 ELSE Log.String("unknwon linker "); Log.String(s); Log.Ln; INC(err)
301 END
302 | ":": Log.String("missing argument for option -T"); Log.String(DswOpts.str); Log.Ln; INC(err)
303 | "?": Log.String("unknown option -T"); Log.String(DswOpts.str); Log.Ln; INC(err)
304 | 0X: Log.String("unknown option -T"); Log.Ln; INC(err)
305 END
306 END ParseTargetOpts;
308 PROCEDURE ParseCommandOpts;
309 BEGIN
310 CASE DswOpts.GetOpt("g:i:") OF
311 | "g": cpcArgs := ToStringList(DswOpts.str);
312 | "i": cplArgs := ToStringList(DswOpts.str);
313 | ":": Log.String("missing argument for option -C"); Log.String(DswOpts.str); Log.Ln; INC(err)
314 | "?": Log.String("unknown option -C"); Log.String(DswOpts.str); Log.Ln; INC(err)
315 | 0X: Log.String("unknown option -C"); Log.Ln; INC(err)
316 END
317 END ParseCommandOpts;
319 PROCEDURE ParseExternalOpts;
320 BEGIN
321 CASE DswOpts.GetOpt("g:i:") OF
322 | "g": cpcExe := DswOpts.str;
323 | "i": cplExe := DswOpts.str;
324 | ":": Log.String("missing argument for option -X"); Log.String(DswOpts.str); Log.Ln; INC(err)
325 | "?": Log.String("unknown option -X"); Log.String(DswOpts.str); Log.Ln; INC(err)
326 | 0X: Log.String("unknown option -X"); Log.Ln; INC(err)
327 END
328 END ParseExternalOpts;
330 PROCEDURE ParseArgs;
331 BEGIN
332 exe := NIL; auto := FALSE; jobs := 1; def.next := NIL; mno := 0; rno := 0;
333 processor := anymach; os := anyos; compiler := anycp;
334 LOOP
335 CASE DswOpts.GetOpt("ao:j:D:U:TCXh") OF
336 | "a": auto := TRUE
337 | "o": exe := DswOpts.str
338 | "j": jobs := MIN(MAX(StrToInt(DswOpts.str, 1), 1), maxJobs)
339 | "h": Help
340 | "D": Define(DswOpts.str)
341 | "U": Undefine(DswOpts.str)
342 | "T": ParseTargetOpts
343 | "C": ParseCommandOpts
344 | "X": ParseExternalOpts
345 | ":": Log.String("missing argument for option -"); Log.String(DswOpts.str); Log.Ln; INC(err)
346 | "?": Log.String("unknown option -"); Log.String(DswOpts.str); Log.Ln; INC(err)
347 | "$": AddModule(DswOpts.str, def)
348 | 0X: EXIT
349 END
350 END
351 END ParseArgs;
353 PROCEDURE CheckParams;
354 BEGIN
355 IF compiler = anycp THEN
356 Log.String("compiler not selected"); Log.Ln; INC(err)
357 ELSIF compiler = cpnative THEN
358 IF processor = anymach THEN
359 Log.String("processor not selected"); Log.Ln; INC(err)
360 ELSIF processor # mach386 THEN
361 Log.String("processor not supported by native compiler"); Log.Ln; INC(err)
362 END
363 END;
364 IF (compiler = cpfront) & (linker # anyint) THEN
365 Log.String("internal linker not required for cpfront"); Log.Ln; INC(err)
366 END;
367 IF (compiler = cpfront) & (exe # NIL) THEN
368 Log.String("cpfront can't out executable file"); Log.Ln; INC(err)
369 END;
370 IF (exe # NIL) & (compiler = cpnative) & (linker = anyint) THEN
371 Log.String("linker not selected"); Log.Ln; INC(err)
372 END;
373 IF (linker = dev2) & (os = anyos) THEN
374 Log.String("os not selected"); Log.Ln; INC(err)
375 END;
376 IF (exe # NIL) & (exe^ = "") THEN
377 Log.String("output file name can't be empty"); Log.Ln; INC(err)
378 END;
379 IF cpcExe = NIL THEN
380 IF compiler = cpnative THEN cpcExe := NewStr("cpc486")
381 ELSIF compiler = cpfront THEN cpcExe := NewStr("cpfront")
382 END
383 END;
384 IF cplExe = NIL THEN
385 IF linker = dev2 THEN cplExe := NewStr("cpl486") END
386 END
387 END CheckParams;
389 (* --------- loader --------- *)
391 PROCEDURE Import (m: Module; IN name: DevCPT.Name);
392 VAR i, j: INTEGER; imp: Module;
393 BEGIN
394 ASSERT(m # NIL, 20);
395 ASSERT(name # "", 21);
396 IF debugImport THEN Log.String(" import "); Log.String(name$) END;
397 IF name = "SYSTEM" THEN INCL(DevCPM.options, DevCPM.sysImp)
398 ELSIF name = "COM" THEN INCL(DevCPM.options, DevCPM.com)
399 ELSIF name = "JAVA" THEN INCL(DevCPM.options, DevCPM.java)
400 ELSE
401 IF debugImport THEN Log.Char(" ") END;
402 i := 0; (* find module in local list *)
403 WHILE (i < m.mno) & (m.imp[i].name$ # name$) DO INC(i) END;
404 IF i >= m.mno THEN
405 j := 0; (* find module in global list *)
406 WHILE (j < mno) & (modList[j].name$ # name$) DO INC(j) END;
407 IF j >= mno THEN
408 NEW(imp); imp.name := name$; imp.selectors := CopySelectorList(m.selectors);
409 modList[mno] := imp; INC(mno)
410 ELSE
411 imp := modList[j]
412 END;
413 m.imp[m.mno] := imp; INC(m.mno)
414 ELSE DevCPM.err(1)
415 END
416 END;
417 IF debugImport THEN Log.Ln END;
418 END Import;
420 PROCEDURE ParseModule (m: Module);
421 VAR sym: BYTE; SelfName, impName, aliasName: DevCPT.Name;
423 PROCEDURE err (n: SHORTINT);
424 BEGIN DevCPM.err(n)
425 END err;
427 PROCEDURE CheckSym(s: SHORTINT);
428 BEGIN
429 IF sym = s THEN DevCPS.Get(sym) ELSE DevCPM.err(s) END
430 END CheckSym;
432 BEGIN
433 IF debugImport THEN Log.String("module " + m.name); Log.Ln END;
434 DevCPS.Init; DevCPS.Get(sym);
435 IF sym = module THEN DevCPS.Get(sym) ELSE err(16) END;
436 IF sym = ident THEN
437 SelfName := DevCPS.name$; DevCPS.Get(sym);
438 IF sym = lbrak THEN
439 INCL(DevCPM.options, DevCPM.interface); DevCPS.Get(sym);
440 IF sym = eql THEN DevCPS.Get(sym)
441 ELSE INCL(DevCPM.options, DevCPM.noCode)
442 END;
443 IF sym = string THEN INCL(m.flags, library); DevCPS.Get(sym)
444 ELSE err(string)
445 END;
446 CheckSym(rbrak)
447 END;
448 CheckSym(semicolon);
449 IF sym = import THEN DevCPS.Get(sym);
450 LOOP
451 IF sym = ident THEN
452 aliasName := DevCPS.name$; impName := aliasName$; DevCPS.Get(sym);
453 IF sym = becomes THEN DevCPS.Get(sym);
454 IF sym = ident THEN impName := DevCPS.name$; DevCPS.Get(sym) ELSE err(ident) END
455 END;
456 Import(m, impName)
457 ELSE err(ident)
458 END;
459 IF sym = comma THEN DevCPS.Get(sym)
460 ELSIF sym = ident THEN err(comma)
461 ELSE EXIT
462 END
463 END;
464 CheckSym(semicolon)
465 END
466 ELSE err(ident)
467 END;
468 DevCPS.str := NIL
469 END ParseModule;
471 PROCEDURE CheckModule (m: Module; source: String; OUT ok: BOOLEAN);
472 VAR s: Selector;
473 BEGIN
474 DevCPM.Init(source);
475 (*
476 DevCPM.symList := m.insym;
477 DevCPM.codePath := m.outcode;
478 DevCPM.symPath := m.outsym;
479 *)
480 DevCPM.name := m.name$;
481 (*
482 IF m.found THEN INCL(DevCPM.options, DevCPM.comAware) END;
483 IF errorTrap IN m.opts THEN INCL(DevCPM.options, DevCPM.trap) END;
484 IF oberon IN m.opts THEN INCL(DevCPM.options, DevCPM.oberon) END;
485 *)
486 DevCPR.Init;
487 s := m.selectors.next;
488 WHILE s # NIL DO
489 DevCPR.Set(s.name, s.value);
490 s := s.next
491 END;
492 ParseModule(m);
493 DevCPR.Check;
494 ok := DevCPM.noerr;
495 DevCPR.Close;
496 DevCPM.InsertMarks;
497 DevCPM.Close;
498 Kernel.FastCollect
499 END CheckModule;
501 PROCEDURE GetSource (IN modName: ARRAY OF CHAR; OUT path: Files.Name; OUT s: String);
502 CONST modDir = "Mod"; sysDir = "System";
503 VAR dir, name: Files.Name; loc: Files.Locator;
504 text: DswDocuments.Model; r: DswDocuments.Reader; i, res: INTEGER;
506 PROCEDURE MakePath (dir, name: Files.Name; type: Files.Type; OUT path: Files.Name);
507 BEGIN
508 ASSERT(name # "", 21);
509 IF dir = "" THEN path := modDir + "/" + name
510 ELSE path := dir + "/" + modDir + "/" + name
511 END;
512 Kernel.MakeFileName(path, type)
513 END MakePath;
515 BEGIN
516 s := NIL; path := "";
517 Kernel.SplitName(modName, dir, name);
518 loc := Files.dir.This(dir).This(modDir);
519 (* --> Kernel.MakeFileName(name, Kernel.docType); <-- *)
520 MakePath(dir, name, "cp", path);
521 DswDocuments.Open(loc, name + ".cp", text, res);
522 IF text = NIL THEN
523 MakePath(dir, name, "odc", path);
524 DswDocuments.Open(loc, name + ".odc", text, res);
525 IF (text = NIL) & (dir = "") THEN
526 MakePath(sysDir, name, "cp", path);
527 loc := Files.dir.This(sysDir).This(modDir);
528 DswDocuments.Open(loc, name + ".cp", text, res);
529 IF text = NIL THEN
530 MakePath(sysDir, name, "odc", path);
531 DswDocuments.Open(loc, name + ".odc", text, res);
532 IF text = NIL THEN
533 path := ""
534 END
535 END
536 END
537 END;
538 IF text # NIL THEN
539 NEW(s, text.Length() + 1);
540 IF s # NIL THEN
541 r := text.NewReader(NIL);
542 FOR i := 0 TO text.Length() - 1 DO
543 r.Read; s[i] := r.char
544 END
545 END
546 END
547 END GetSource;
549 PROCEDURE Trace (m, parent: Module; VAR lno: INTEGER);
550 VAR i: INTEGER;
551 BEGIN
552 IF ~(trace IN m.flags) THEN
553 INCL(m.flags, trace);
554 FOR i := 0 TO m.mno - 1 DO
555 Trace(m.imp[i], m, lno);
556 m.depth := MAX(m.depth, m.imp[i].depth + 1)
557 END;
558 IF ~(imported IN m.flags) THEN
559 INCL(m.flags, imported);
560 lnkList[lno] := m;
561 INC(lno)
562 END;
563 EXCL(m.flags, trace)
564 ELSE
565 Log.String("recursive import of " + m.name + " in " + parent.name); Log.Ln; INC(err)
566 END
567 END Trace;
569 PROCEDURE Sort;
570 VAR i, j: INTEGER; m: Module;
571 BEGIN
572 ASSERT((mno = 0) OR (lnkList[0] # NIL), 20);
573 cmpList := lnkList;
574 i := 1;
575 WHILE i < mno DO
576 m := cmpList[i];
577 j := i - 1;
578 WHILE (j >= 0) & (cmpList[j].depth > m.depth) DO
579 cmpList[j + 1] := cmpList[j];
580 DEC(j)
581 END;
582 cmpList[j + 1] := m;
583 INC(i)
584 END
585 END Sort;
587 PROCEDURE CheckDeps;
588 VAR i, j, num: INTEGER; m: Module; s: String; ok: BOOLEAN;
589 BEGIN
590 i := 0; rno := mno;
591 WHILE (err = 0) & (i < mno) DO
592 m := modList[i];
593 GetSource(m.name$, m.path, s);
594 IF s # NIL THEN
595 CheckModule(m, s, ok);
596 IF ~ok THEN INC(err) END
597 ELSE
598 Log.String("unable to open module " + m.name); Log.Ln; INC(err)
599 END;
600 INC(i)
601 END;
602 num := 0;
603 FOR i := 0 TO rno - 1 DO
604 Trace(modList[i], modList[i], num)
605 END;
606 ASSERT((err # 0) OR (num = mno), 100);
607 Sort;
608 IF debugOrder THEN
609 Log.String("Parallel depth:"); Log.Ln;
610 FOR i := 0 TO mno - 1 DO
611 Log.String(" " + cmpList[i].name); Log.Int(cmpList[i].depth); Log.Ln;
612 END
613 END
614 END CheckDeps;
616 PROCEDURE IsCompiled (m: Module): BOOLEAN;
617 CONST target = {hasSym, hasObj};
618 VAR i: INTEGER; ready: BOOLEAN;
619 BEGIN
620 ASSERT(m # NIL, 20);
621 i := 0;
622 ready := ~(hasErrors IN m.flags) & (m.flags * target = target);
623 WHILE ready & (i < m.mno) DO
624 ready := IsCompiled(m.imp[i]);
625 INC(i)
626 END;
627 RETURN ready
628 END IsCompiled;
630 PROCEDURE Ready (m: Module): BOOLEAN;
631 CONST target = {hasSym, hasObj};
632 VAR i: INTEGER; ready: BOOLEAN;
633 BEGIN
634 i := 0;
635 ready := ~(hasErrors IN m.flags) & (m.flags * target # target) & (m.worker = NIL);
636 WHILE ready & (i < m.mno) DO
637 ready := IsCompiled(m.imp[i]);
638 INC(i)
639 END;
640 RETURN ready
641 END Ready;
643 PROCEDURE PutParams (w: DswProcs.Process; p: StringList);
644 VAR i: INTEGER;
645 BEGIN
646 ASSERT(w # NIL, 20);
647 IF debugArgs THEN Log.String("PutParams") END;
648 IF p # NIL THEN
649 IF debugArgs THEN Log.String(":[" + p[0]) END;
650 w.PutParam(p[0]);
651 FOR i := 1 TO LEN(p) - 1 DO
652 IF debugArgs THEN Log.String("|" + p[i]) END;
653 w.PutParam(p[i])
654 END;
655 IF debugArgs THEN Log.Char("]") END
656 END;
657 IF debugArgs THEN Log.Ln END
658 END PutParams;
660 PROCEDURE ExecuteCompiler (m: Module): DswProcs.Process;
661 VAR w: DswProcs.Process; ok: BOOLEAN;
662 BEGIN
663 ASSERT(m # NIL, 20);
664 ASSERT(m.path # "", 21);
665 ASSERT(m.worker = NIL, 22);
666 w := DswProcs.dir.New();
667 w.Program(cpcExe);
668 w.PutParam("-legacy");
669 PutParams(w, cpcArgs);
670 w.PutParam(m.path);
671 w.Execute(ok);
672 IF ok THEN
673 Log.String("Compile " + m.name + " (" + m.path + ")"); Log.Ln;
674 ELSE
675 w := NIL
676 END;
677 RETURN w
678 END ExecuteCompiler;
680 PROCEDURE Compile;
681 VAR i, j, num: INTEGER; ok: BOOLEAN; m: Module; w: DswProcs.Process;
682 BEGIN
683 IF mno = 0 THEN RETURN END;
684 num := 0; j := 0;
685 WHILE (err = 0) & (num < mno) OR (j > 0) DO
686 i := 0;
687 WHILE (err = 0) & (i < mno) & (j < jobs) DO
688 m := cmpList[i];
689 IF Ready(m) THEN
690 w := ExecuteCompiler(m);
691 IF debugJobs THEN Log.String("Start job " + m.name) END;
692 IF w # NIL THEN
693 IF debugJobs THEN Log.String(" ok") END;
694 m.worker := w;
695 INC(j)
696 ELSE
697 IF debugJobs THEN Log.String(" fail") END;
698 INCL(m.flags, hasErrors);
699 INC(err)
700 END;
701 IF debugJobs THEN Log.Ln END
702 END;
703 INC(i)
704 END;
705 WHILE (err = 0) & (j >= jobs) OR (j > 0) DO
706 i := 0;
707 WHILE (j > 0) & (i < mno) DO
708 m := cmpList[i];
709 w := m.worker;
710 IF (w # NIL) & w.IsTerminated() THEN
711 IF debugJobs THEN Log.String("Stop job " + m.name); Log.Int(w.Result()); Log.Ln END;
712 IF w.Result() = 0 THEN
713 INCL(m.flags, hasObj);
714 INCL(m.flags, hasSym);
715 INC(num)
716 ELSE
717 INCL(m.flags, hasErrors);
718 INC(err)
719 END;
720 m.worker := NIL;
721 DEC(j)
722 END;
723 INC(i)
724 END
725 END
726 END
727 END Compile;
729 PROCEDURE LinkDev2;
730 VAR p: DswProcs.Process; i, res: INTEGER; ok: BOOLEAN;
731 BEGIN
732 ASSERT((exe # NIL) & (exe^ # ""), 20);
733 ASSERT(processor = mach386, 21);
734 ASSERT(compiler = cpnative, 22);
735 ASSERT(os IN {linux, freebsd, openbsd, win32}, 23);
736 p := DswProcs.dir.New();
737 p.Program(cplExe);
738 IF os # anyos THEN
739 p.PutParam("-os");
740 CASE os OF
741 | linux: p.PutParam("linux")
742 | freebsd: p.PutParam("freebsd")
743 | openbsd: p.PutParam("openbsd")
744 | win32: p.PutParam("win32")
745 END
746 END;
747 p.PutParam("-kernel");
748 p.PutParam("Kernel");
749 p.PutParam("-main");
750 p.PutParam("Kernel");
751 p.PutParam("-legacycodedir");
752 p.PutParam(".");
753 p.PutParam("-o");
754 p.PutParam(exe);
755 PutParams(p, cplArgs);
756 i := 0;
757 WHILE i < mno DO
758 IF ~(library IN lnkList[i].flags) THEN
759 p.PutParam(lnkList[i].name$)
760 END;
761 INC(i)
762 END;
763 p.Execute(ok);
764 IF ok THEN
765 Log.String("Link "); Log.String(exe); Log.Ln;
766 res := p.Result();
767 IF res # 0 THEN
768 Log.String("linker terminated with error"); Log.Int(res); Log.Ln;
769 INC(err)
770 END
771 ELSE
772 Log.String("unable to execute linker"); Log.Int(i); Log.Ln;
773 INC(err)
774 END
775 END LinkDev2;
777 PROCEDURE Link;
778 BEGIN
779 IF exe # NIL THEN
780 CASE linker OF
781 | anyint: (* do not link *)
782 | dev2: LinkDev2
783 END
784 END
785 END Link;
787 PROCEDURE Main;
788 VAR m: Module; s: Selector; p: DswProcs.Process; ok: BOOLEAN; i, res: INTEGER;
789 BEGIN
790 IF Kernel.trapCount = 0 THEN
791 ParseArgs;
792 IF err = 0 THEN
793 CheckParams;
794 IF err = 0 THEN
795 CheckDeps;
796 IF err = 0 THEN
797 Compile;
798 IF err = 0 THEN
799 Link
800 END
801 END
802 END
803 END
804 ELSE INC(err)
805 END;
806 IF err = 0 THEN Kernel.Quit(0)
807 ELSE Kernel.Quit(1)
808 END;
809 END Main;
811 BEGIN
812 NEW(def);
813 Kernel.Start(Main)
814 END DswMakeMain.