DEADSOFTWARE

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